简体   繁体   中英

Using h:selectBooleanCheckbox to delete multiple rows in JSF datatable

I have followed the instruction as per the posts How to select multiple rows of <h:dataTable> with <h:selectBooleanCheckbox> and Using <h:selectBooleanCheckbox> with Map in a paginated <p:dataTable> throws NullPointerException on how to delete multiple rows from a datatable. However, the checked Map object is not being populated with the the selected values. When I debug the application it is always empty.

Here is my code: applicantSearch.xhtml

 <ui:composition template="/WEB-INF/templates/main.xhtml"> 

<ui:define name="menu">
    <ui:include src="/protected/views/menu.xhtml"/>
</ui:define>    

<ui:define name="content">

    <h:outputScript target="body">
      formatMyTable();

    </h:outputScript>
    <h3>Search for Applicants</h3>
    <h:form id="searchForm" class="form-search">    
       <h:panelGroup id="results" class="table-responsive">   


           <h:outputText id="informationMessage" 
                         value="#{applicantSearchBacking.infoMessage}" 
                         rendered="#{applicantSearchBacking.infoMessage ne null}"
                         class="informationMessage"/>
            <div class="btn-toolbar">
            <h:commandButton value="Delete Selected" onclick="if (! confirm('Are you sure you want to delete the selected applicants?')) return false" action="#{applicantSearchBacking.removeSelectedApplicants}" class="btn btn-danger btn-large pull-right">
                            <f:ajax render=":searchForm:results :searchForm:messages" onevent="formatMyTable" 
                                    />
             </h:commandButton>
            </div>
           <br/>
           <h:dataTable value="#{applicantSearchBacking.applicantList}" 
                        var="currentApplicant" styleClass="table table-hover table-condensed table-bordered"   
                        >

               <h:column>
                   <f:facet name="header">
                       Applicant ID
                   </f:facet>
                   #{currentApplicant.applicantId}
               </h:column>
               <h:column>
                   <f:facet name="header">
                       First Name
                   </f:facet>
                   #{currentApplicant.firstName}
               </h:column>                   
               <h:column>
                   <f:facet name="header">
                       Middle Name
                   </f:facet>
                   #{currentApplicant.middleName}
               </h:column>   

               <h:column>
                   <f:facet name="header">
                       Last Name
                   </f:facet>
                   #{currentApplicant.lastName}
               </h:column>   

               <h:column>
                   <f:facet name="header">
                       Actions
                   </f:facet>

                   <!-- User Access control section <c:if test=""> -->
                   <h:link value="Edit" outcome="#{applicantSearchBacking.editApplicant()}" class="btn btn-primary btn-sm">
                       <f:param name="myApplicantId" value="#{currentApplicant.applicantId}">
                       </f:param>
                   </h:link>    
                  <!-- </c:if> -->

                   <!-- <c:if test=""> -->
                 <h:selectBooleanCheckbox id="del_checkbox"  value="#{applicantSearchBacking.checked[currentApplicant.applicantId]}">

                 </h:selectBooleanCheckbox>   

                  <!-- </c:if> -->

               </h:column>                     

           </h:dataTable> 


       </h:panelGroup>  

       <h:messages id="messages" class="errorMessage"/>
    </h:form>
</ui:define>

applicantSearchBacking.java

private Map<Integer, Boolean> checked = new HashMap<>(); 

 public void removeSelectedApplicants()
{

     try {
         List<Applicant> applicantsToDelete = new ArrayList<>();

        for (Applicant applicant : applicantList) {
            Boolean itemChecked = checked.get((applicant.getApplicantId()));

        if (itemChecked !=null && itemChecked) {
            applicantsToDelete.add(applicant);
    }
    }

    applicantManager.removeSelectedApplicants(applicantsToDelete);
    if (!checked.isEmpty())
        infoMessage = "Applicant(s) deleted successfully";


    checked.clear();

}

This construct will only work if exactly the same data model is preserved for the postback. So, if your bean is @RequestScoped , then it must be creating exactly the same applicantList inside @PostConstruct as it was when the form was displayed. Otherwise, you need to make the bean @ViewScoped . In any case, I assume that the getter method of applicantList doesn't do any business logic, but just solely returns the property.

See also:


As per your question update, there's another potential mistake which may cause this construct to fail:

<f:ajax render=":searchForm:results :searchForm:messages" onevent="formatMyTable" />

The execute of <f:ajax> is here unspecified and uses then thus the default of @this . You need to explicitly specifiy @form in order to process the entire form on submit, otherwise only the parent component (the command button itself) would be processed.

<f:ajax execute="@form" ... />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM