Search code examples
jqueryjsfprimefacesselectallselectmanycheckbox

Select all items in Multiple SelectManyCheckBox with dynamic ids


I want to select all check box in some groups of checkboxes using PrimeFaces component on top of JSF.

My code is like this:

<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
    <p:outputLabel value="Confere:" style="font-weight:bold!important" />
    <p:selectManyCheckbox
        value="#{funcionarioBean.funcionario.permissaoConfere.stringArray}">
        <f:selectItem itemLabel="Consulta" itemValue="C" />
        <f:selectItem itemLabel="Edição" itemValue="E" />
        <f:selectItem itemLabel="Deleção" itemValue="D" />
        <f:selectItem itemLabel="Inclusão" itemValue="I" />
        <f:selectItem itemLabel="Relatório" itemValue="R" />
        <f:selectItem itemLabel="Check All"/>
    </p:selectManyCheckbox>
</h:panelGrid>
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
    <p:outputLabel value="Visitante:" style="font-weight:bold!important" />
    <p:selectManyCheckbox
        value="#{funcionarioBean.funcionario.permissaoVisitante.stringArray}">
        <f:selectItem itemLabel="Consulta" itemValue="C" />
        <f:selectItem itemLabel="Edição" itemValue="E" />
        <f:selectItem itemLabel="Deleção" itemValue="D" />
        <f:selectItem itemLabel="Inclusão" itemValue="I" />
        <f:selectItem itemLabel="Relatório" itemValue="R" />
        <f:selectItem itemLabel="Check All"/>
    </p:selectManyCheckbox>
</h:panelGrid>
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
    <p:outputLabel value="Ocorrências:" style="font-weight:bold!important" />
    <p:selectManyCheckbox
        value="#{funcionarioBean.funcionario.permissaoOcorrencia.stringArray}">
        <f:selectItem itemLabel="Consulta" itemValue="C" />
        <f:selectItem itemLabel="Edição" itemValue="E" />
        <f:selectItem itemLabel="Deleção" itemValue="D" />
        <f:selectItem itemLabel="Inclusão" itemValue="I" />
        <f:selectItem itemLabel="Relatório" itemValue="R" />
        <f:selectItem itemLabel="Check All"/>
    </p:selectManyCheckbox>
</h:panelGrid>

I tried with the code posted here but it only works, if you have only one group of checkboxes on the page.


Solution

  • Wrap it in a reusable composite component like below:

    /resources/composites/selectManyCheckboxAll.xhtml

    <ui:component
        xmlns="http://www.w3.org/1999/xhtml"
        xmlns:f="http://xmlns.jcp.org/jsf/core"
        xmlns:h="http://xmlns.jcp.org/jsf/html"
        xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
        xmlns:cc="http://xmlns.jcp.org/jsf/composite"
        xmlns:p="http://primefaces.org/ui"
    >
        <cc:interface>
            <cc:attribute name="value" />
            <cc:editableValueHolder name="input" targets="checkboxes" />
        </cc:interface>
        <cc:implementation>
            <h:outputStylesheet library="composites" name="selectManyCheckboxAll.css" target="head" />
            <h:outputScript library="composites" name="selectManyCheckboxAll.js" target="head" />
            <div id="#{cc.clientId}" class="checkboxes-all" 
                data-widget-checkboxes="#{p:widgetVarFromContext('checkboxes', cc).split('\'')[1]}" 
                data-widget-all="#{p:widgetVarFromContext('all', cc).split('\'')[1]}">
                <p:selectManyCheckbox id="checkboxes" value="#{cc.attrs.value}">
                    <cc:insertChildren />
                </p:selectManyCheckbox>
                <div class="all">
                    <p:selectBooleanCheckbox id="all" />
                    <p:outputLabel for="all" value="Check all" />
                </div>
            </div>
        </cc:implementation>          
    </ui:component>
    

    /resources/composites/selectManyCheckboxAll.css

    .checkboxes-all {
        white-space:  nowrap;
    }
    
    .checkboxes-all .ui-selectmanycheckbox,
    .checkboxes-all .all {
        display: inline-block;
        vertical-align: middle;
    }
    
    .checkboxes-all .all .ui-chkbox {
        margin: 1px 4px 0 0;
        vertical-align: top;
    }
    
    .checkboxes-all .all label {
        display: inline-block;
        margin-top: 4px;
    }
    

    /resources/composites/selectManyCheckboxAll.js

    $(document).on("click", ".checkboxes-all .all .ui-chkbox-box, .checkboxes-all .all input", function() {
        var $composite = $(this).closest(".checkboxes-all");
        var widgetAll = PrimeFaces.widgets[$composite.data("widget-all")];
        var widgetCheckboxes = PrimeFaces.widgets[$composite.data("widget-checkboxes")];
    
        widgetCheckboxes.inputs.prop("checked", !widgetAll.isChecked()).click();
    });
    
    $(document).on("click", ".checkboxes-all .ui-selectmanycheckbox input", function() {
        var $composite = $(this).closest(".checkboxes-all");
        var widgetAll = PrimeFaces.widgets[$composite.data("widget-all")];
    
        if (!$(this).is(":checked") && widgetAll.isChecked()) {
            widgetAll.uncheck();
        }
    });
    

    Usage:

    <html xmlns:my="http://xmlns.jcp.org/jsf/composite/composites">
    ...
    <my:selectManyCheckboxAll value="#{bean.selectedItems}">
        <f:selectItem itemLabel="Consulta" itemValue="C" />
        <f:selectItem itemLabel="Edição" itemValue="E" />
        <f:selectItem itemLabel="Deleção" itemValue="D" />
        <f:selectItem itemLabel="Inclusão" itemValue="I" />
        <f:selectItem itemLabel="Relatório" itemValue="R" />
    </my:selectManyCheckboxAll>