Search code examples
checkboxrichfacesjsf-2.2

JSF-2 Select/Unselect all the list of checkboxes with single checkbox


I have list of check boxes inside rich:dataTable and I want to check all the boxes at once with a single check box from header column.

<rich:column id="includeInWHMapping" >
      <f:facet name="header">
        <h:selectBooleanCheckbox value="#{checkallbox.selectAll}">
           <f:ajax actionListener="#{checkallbox.selectAllBox}" render="selectedForWHProcess" />
        </h:selectBooleanCheckbox>  
      </f:facet>        
      <h:selectBooleanCheckbox id="selectedForWHProcess" value="#{checkallbox.checked[data]}">      
         <f:ajax actionListener="#{checkallbox.selectAllRows}"/>
      </h:selectBooleanCheckbox></rich:column>

Code in checkallbox Bean:

private Map<StandardStructure, Boolean> checked = new HashMap<StandardStructure, Boolean>();        
private boolean selectAll;

public boolean isSelectAll() {
    return selectAll;
}

public void setSelectAll(boolean selectAll) {
    this.selectAll = selectAll;
}

public Map<StandardStructure, Boolean> getChecked() {
    return checked;
}

public void setChecked(Map<StandardStructure, Boolean> checked) {
    this.checked = checked;
}

public void selectAllBox(ValueChangeEvent e){
    boolean newSelectAll = (Boolean) e.getNewValue();
    Iterator<StandardStructure> keys = checked.keySet().iterator();
    while(keys.hasNext()){
        StandardStructure ss = keys.next();
        checked.put(ss, newSelectAll);
    }
}

When I check the h:selectBooleanCheckBox of header column nothing happens. What am I missing here? Should I have to implement Map for "selectAll" property too?

Thanks.


Solution

  • First of all. f:ajax doesn't have actionListener, it has a listener. Read the docs here. Second thing, you can use valueChangeListener on h:selectBooleanCheckbox and only there. Third, listener inside rows boxes is wrong. Basically, it looks like you need to read this topic.

    Now, here is the working example:

    <h:form>
        <rich:dataTable value="#{checkallbox.allValues}" var="data" id="dataTable">
            <rich:column>
                <f:facet name="header">
                    <h:selectBooleanCheckbox value="#{checkallbox.selectAll}"
                        valueChangeListener="#{checkallbox.selectAllBox}">
                        <f:ajax render="dataTable" />
                    </h:selectBooleanCheckbox>
                </f:facet>
                <h:selectBooleanCheckbox value="#{checkallbox.checked[data]}">
                    <f:ajax />
                </h:selectBooleanCheckbox>
            </rich:column>
    
            <!-- other columns -->
        </rich:dataTable>
    </h:form>
    

    Other possible problems with your code (since you've shared just a part).

    • The data table needs to be in form, since you're executing ajax inside.
    • Your keys in map are objects. You have to make sure that equals method is good. In 95% of case the default is not, especially if they are @Entity.
    • You have to make sure that the map is populated with false at the beginning. I use @PostConstruct:

      @PostConstruct
      protected void performPostConstructAction() {
          for (StandardStructure s : getAllValues()) {
              checked.put(s, false);
          }
      }