How can I get the clicked item in the ajax method?

16,094

You're thus interested in the actual value change and not only in the new value. Bring in a valueChangeListener which compares the old value with the new value and prepares some properties which the ajax listener method could intercept on.

E.g.

<h:selectManyCheckbox value="#{bean.selectedItems}" valueChangeListener="#{bean.selectedItemsChanged}" converter="javax.faces.Long">
    <f:selectItems value="#{bean.availableItems}" />
    <f:ajax listener="#{bean.itemSelected}" />
</h:selectManyCheckbox>

with

private Map<String, Long> availableItems; // +getter
private List<Long> selectedItems; // +getter+setter
private Long selectedItem;
private boolean selectedItemRemoved;

@PostConstruct
public void init() {
    availableItems = new LinkedHashMap<String, Long>();

    for (long i = 0; i < 10; i++) {
        availableItems.put("CHKID " + i, i);
    }
}

public void selectedItemsChanged(ValueChangeEvent event) {
    List<Long> oldValue = (List<Long>) event.getOldValue();
    List<Long> newValue = (List<Long>) event.getNewValue();

    if (oldValue == null) {
        oldValue = Collections.emptyList();
    }

    if (oldValue.size() > newValue.size()) {
        oldValue = new ArrayList<Long>(oldValue);
        oldValue.removeAll(newValue);
        selectedItem = oldValue.iterator().next();
        selectedItemRemoved = true;
    }
    else {
        newValue = new ArrayList<Long>(newValue);
        newValue.removeAll(oldValue);
        selectedItem = newValue.iterator().next();
        selectedItemRemoved = false;
    }
}

public void itemSelected(AjaxBehaviorEvent event) {
    System.out.println("Selected item: " + selectedItem);
    System.out.println("Selected item removed? " + selectedItemRemoved);
}
Share:
16,094
yersan
Author by

yersan

Updated on July 24, 2022

Comments

  • yersan
    yersan almost 2 years

    Suppose the code of this page:

    <h:form prependId="false" id="form">
    
        <h:selectManyCheckbox id="checkBoxList" value="#{backedBean.lstIdSelectedItems}" layout="pageDirection">
            <f:selectItems value="#{backedBean.lstAvailableItems}" var="item" itemLabel="#{item.label}" itemValue="#{item.value}" />
            <f:ajax listener="#{backedBean.itemClicked}" />
        </h:selectManyCheckbox>
    
    </h:form>
    

    And the code of a session managed bean:

    public class BackedBean implements Serializable {
       private List<SelectItem> lstAvailableItems;
       private List<Long> lstIdSelectedItems;
    
    public BackedBean() {
        lstAvailableItems = new ArrayList<SelectItem>();
        lstIdSelectedItems = new ArrayList<Long>();
    }
    
    @PostConstruct
    private void postConstruct(){
        for (int i = 0; i < 10; i++) {
            SelectItem item = new SelectItem(new Long(i), "CHKID " + i);
            lstAvailableItems.add(item);
        }
    }
    
    public void itemClicked(AjaxBehaviorEvent ae){
        HtmlSelectManyCheckbox uiCmp = (HtmlSelectManyCheckbox)ae.getSource();
    
        // (1) Here I would like to get the ID of the item that has been clicked.
    
    }
    

    In (1) I would like to get the ID of the element that has been clicked by the user. I can see in the lstIdSelectedItems array list the IDs of all elements selected by the user, but how can I get the ID of the element that the user has clicked?

    I have tried to use the f:attribute tag inside of the selectManyCheckbox, but the attribute is not in the component map when the ajax listener method is called in the backed bean. I have used this, but doesn't work:

    <h:selectManyCheckbox id="checkBoxList" value="#{backedBean.lstIdSelectedItems}" layout="pageDirection">
        <f:selectItems value="#{backedBean.lstAvailableItems}" var="item" itemLabel="#{item.label}" itemValue="#{item.value}">
            <f:attribute name="clicked" value="#{item.value}" />
        </f:selectItems>
        <f:ajax listener="#{backedBean.itemClicked}" />
    </h:selectManyCheckbox>
    

    Any ideas?

    Regards.