Finding selected checkbox items in a JSF dataTable

This is one of those problems that I couldn’t find a complete example for when I needed it, so hopefully this will save somebody else the extra time it took me to piece it together.

We frequently need to have data tables in our UI, and allow the user to select a subset of those items for action. In JavaServer Faces, this means having a DataTable, each row having its own checkbox. But when the action is triggered, how to we find which items the user has selected.

The first step is to add a boolean property to your objects that can represent the selection. If you have a lot objects in your domain that will need this property, you may want to consider adding this to an interface or parent bean, otherwise, you can add it directly to your domain object. As a caveat, I don’t like adding properties to my domain objects that are for UI use only, but in this case, I’m keeping this as simple as possible. Sometimes pragmatism wins.

package com.stevideter.domain;
 
public class SelectableItem {
 
  private Integer id;
  private String name;
  private boolean selected;
 
  public Integer getId() {
    return id;
  }
 
  public void setId(Integer id) {
    this.id = id;
  }
 
  public String getName() {
    return name;
  }
 
  public void setName(String name) {
    this.name = name;
  }
 
  public boolean isSelected() {
    return selected;
  }
 
  public void setSelected(boolean selected) {
    this.selected = selected;
  }
}

In your view, you’ll use the dataTable to display the items, including the checkbox:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
 
<f:view><html><body>
<h:form>
<h:dataTable id="itemsTable" 
    value="#{SelectionBean.selectedItems}" var="item"  >
 
<f:facet name="header">
  <h:outputText value="Items" />
</f:facet> 
<h:column>
  <f:facet name="header">
    <h:outputText value="Select" />
  </f:facet>
  <h:selectBooleanCheckbox value="#{item.selected}" />
</h:column>
<h:column>
  <f:facet name="header">
    <h:outputText value="name" />  
  </f:facet> 
    <h:outputText value="#{item.name}"></h:outputText>
</h:column>
</h:dataTable>
<h:commandButton title="selectItems" 
    value="Select Items"
    actionListener="#{SelectionBean.submitSelections}" />
</h:form>
</body></html></f:view>

Now when you click the command button to trigger the submitSelections event, the boolean values for selected items will be set, and you can iterate through your list to find the selected items and act on them as needed.

package com.stevideter.BackingBean;
 
import java.util.List;
 
import javax.faces.event.ActionEvent;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
 
import com.stevideter.domain.SelectableItem;
import com.stevideter.manager.DomainManager;
 
public class SelectionBean {
 
  private DataModel selectableItems;
  private DomainManager manager;
 
  public void populateSelectableItems(ActionEvent event) {
    selectableItems = new ListDataModel();
    selectableItems.add(manager.getSelectableItems());
  }
 
  public void submitSelections(ActionEvent event) {
    List<SelectableItem> items = (List<SelectableItem>)selectableItems.getWrappedData();
    List<SelectableItem> selectedItems = new ArrayList<SelectableItem>();
    for (SelectableItem item : items) {
      if (item.isSelected()) {
        selectedItems.add(item);
      }
    }
    // do what you need to do with selected items
  }
 
  public DataModel getSelectableItems() {
    return selectableItems;
  }
 
  public void setSelectableItems(DataModel selectableItems) {
    this.selectableItems = selectableItems;
  }
}

As you can see, this is a very simple solution. Have you seen any other approaches that work?

26 thoughts on “Finding selected checkbox items in a JSF dataTable

  1. yummy

    Hi :

    What is the purpose of DomainManager class?
    Would you please paste the source code of that class?
    Thanks

  2. stevi Post author

    yummy,

    The DomainManager represents the business layer of the application in this example.

    That’s where you’d put the logic for getting your items from the database, for example, to abstract it from the UI/view layer.

    I didn’t include it in the post since it would be specific to your needs. I should have explicitly said that in the post, so thanks for pointing out that I didn’t.

  3. Rajendra

    Hai Stevi Deter,

    Im new to JSF im developing an applicatiopn in that I’ve a problem:

    Actually i want to edit the user registered values dynamically i used datatable to retrive the values from database and i used radio button to select the perticular record, but it was not working properly so i used java script for selecting the radio-button . now problem is if table having only one row then only it took the values dynamically to the next page to edit if table contains more records then it will not working properly please help me out ..
    Hope u will reply me..

  4. Ana

    There is a bug in the jsp code, in the part:

    where value should have the following value:

    value=”#{backing_selectionBean.selectableItems}”,

    as in the backing bean there is no property of type selectedItems, and there is no sense of presenting selectedItems on GUI, but DataModel selectableItems, for which there are setter/getter and it represents the datatable actually.

    Whit this correction the code works fine.

    Best regards,
    Ana

  5. jianshun

    I’ve tested your code and have some questions. Please correct me if I’m wrong.

    1. what is the bean scope of your “SelectionBean”?
    It seams to me that your code is working only
    if the bean scope is “session”.

    If this is the case, the solution can be simpler:
    Instead of using DataModel, you can just use
    ArrayList as “selectableItems” in the class “SelectBean”.

    and in the function “submitSelections(..)”, simply walk through selectableItems
    and you will get the same results.

    2. Suppose the bean scope of “SelectionBean” is “session”. That would imply that
    all the selectable items will be sitting in the memory on the server side during
    the session period. If the data amount is big and if multiple users are using the same page
    at the same time, it would lead memory problems of the server.

    3. Suppose the bean scope is “request”. Then the function “populateSelectableItems(..)” would have
    to be called in the constructor of the class “SelectionBean” or in a similar way to make sure that once
    “SelectionBean” is instantiated, “selectableItems” is always initialized, or
    “submitSelections(..)” will not work.

    Also, when “populateSelectableItems(..)” is called, “selectableItems” has to refer to the same
    selectable items as they were displayed on the page. Otherwise, “populateSelectableItems(..)” would
    give wrong results.

    Your help will be very appreciated.

  6. stevi Post author

    Ana and Jianshun;
    I’ve been too busy at work to give your comments the fair review they reserve, but I will try soon!

    I did intentionally use the DataModel on purpose to show its use in this context. There’s frequently more than one way to do things, so thanks for showing some alternatives!

  7. varun

    Piece of code was very useful, could you plz also tell, way to refersh data table with new data.

  8. thachthao

    can you tell me how to display list on jsf page. I have the list String and want to display each element on jsf throught datatable

  9. Rajneesh

    We are also using the same approach. But, this approach has a problem

    e.g. you have a list of 10 items, and you used same approach to select the fist time and then perform a delete operation on that.

    Now, once this is done and we have left 9 items in the list. Suppose, you press F5 from IE browser, now image what will be happen?

    It sends, the request again to the server and tables sets again the first time selected because it is on the same index and gets deleted as well.

    I am trying to figure out how to resolve this problem, within same approach.

  10. Geraldo Luiz

    I use a similar aproach. But, like you, I’m also not very fond of messing with my domain objects, introducing an artificial atribute that doesn’t belong there.

    Maybe it’s possible to extend the DataModel abstract class as a MultipleSelectionEntityDataModel or something like that. The default DataModel (and its derived concrete classes) models a single selection collection, so we must add methods to get and set the selected rows indexes, and the implementation of the getRowIndex() and setRowIndex() abstract methods may return, for example, the first selected one.

    It’s just a thought. I will play with this idea, when I have a spare time, and I inform here if I have any success sith this aproach.

  11. novino

    Hi Stevi,

    I tried the same but I’m getting following Exception. Do you have any suggestion on this.

    Thanks.

    java.lang.NullPointerException
    at com.geae.empis.bean.UserBean.deletePan(UserBean.java:298)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:131)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
    at org.apache.jasper.el.JspMethodExpression.invoke(JspMethodExpression.java:68)
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
    at javax.faces.component.UICommand.broadcast(UICommand.java:387)
    at org.ajax4jsf.component.AjaxViewRoot.processEvents(AjaxViewRoot.java:184)
    at org.ajax4jsf.component.AjaxViewRoot.broadcastEvents(AjaxViewRoot.java:162)
    at org.ajax4jsf.component.AjaxViewRoot.processApplication(AjaxViewRoot.java:350)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:82)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:141)
    at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:281)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:228)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:216)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:634)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:445)
    at java.lang.Thread.run(Thread.java:595)

  12. stevi Post author

    novino,
    I’d look at your UserBean.java file at line 298 and figure out why it’s throwing a null pointer exception.

  13. Sathish

    Thanks to all articles and comments , it is very much useful for fresh developers and most of others

    thanks a lot , keep posting like wise articles

  14. Sirisha

    Hi,

    When i tried to add items to javax.faces.model.ListDataModel object, it is showing a compile time error saying ‘add’ method is not supported.

    Can you please let me know how can items be added to ListDataModel object.

    Thanks

  15. zeeshan Akhter

    its really good ……..
    but i want to delete and update selected items from database using <h:selectBooleanCheckbox
    in <h:datamodel tel me how i do that……..

  16. Anshul

    (refering to comment no. 18)

    Novino,
    i have also got the same problem, i am working on it…if anyone else knows the solution then please help.

    This is Exception:
    Dec 15, 2011 1:53:31 PM javax.faces.event.MethodExpressionActionListener processAction
    SEVERE: Received ‘java.lang.NullPointerException’ when invoking action listener ‘#{Shop.submitSelections}’ for component ‘j_id_jsp_1988918580_18′
    Dec 15, 2011 1:53:31 PM javax.faces.event.MethodExpressionActionListener processAction
    SEVERE: java.lang.NullPointerException
    at com.Shop.submitSelections(Shop.java:26)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:172)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
    at org.apache.jasper.el.JspMethodExpression.invoke(JspMethodExpression.java:68)
    at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:99)
    at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
    at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:771)
    at javax.faces.component.UICommand.broadcast(UICommand.java:372)
    at org.ajax4jsf.component.AjaxViewRoot.processEvents(AjaxViewRoot.java:321)
    at org.ajax4jsf.component.AjaxViewRoot.broadcastEvents(AjaxViewRoot.java:296)
    at org.ajax4jsf.component.AjaxViewRoot.processPhase(AjaxViewRoot.java:253)
    at org.ajax4jsf.component.AjaxViewRoot.processApplication(AjaxViewRoot.java:466)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:82)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:619)

    And This is my Shop.java
    package com;

    import java.util.ArrayList;

    import javax.faces.event.ActionEvent;
    import javax.faces.model.DataModel;

    public class Shop {

    private DataModel selectableItems;
    ArrayList items;
    ArrayList selectedItems;

    public String addToCart()
    {

    items = (ArrayList)selectableItems.getWrappedData();

    selectedItems = new ArrayList();

    for (ProductModel item : items) {
    if (item.getChecked()) {
    selectedItems.add(item);
    System.out.print(“\n\nproduct added to cart=”+item.desc+”\n\n”);
    }
    else{
    selectedItems.remove(item);
    System.out.print(“\n\nproduct removed from cart=”+item.desc+”\n\n”);
    }
    }
    return “add_to_cart”;
    }
    public ArrayList getSelectedItems() {
    return selectedItems;
    }
    public void setSelectedItems(ArrayList selectedItems) {
    this.selectedItems = selectedItems;
    }

    }

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>