37

I'm trying to create a DataTable with Multiple Row Selection but i'm getting an error here's the link of the tutorial http://www.primefaces.org/showcase/ui/datatableRowSelectionMultiple.jsf :

Here's my xhtml:

    <p:dataTable border="1" value="#{projectAdminisrationMB.projectNoUsersList}" 
                     var="userObj"
                     selection="#  
         {projectAdminisrationMB.selectedUsers}"
 selectionMode="multiple" rowIndexVar="rowIndex"binding="#{table2}">
<p:column id="column3">
<f:facet name="header">
<h:outputText value=" user "></h:outputText>
</f:facet>

      <h:outputText value="#{userObj.name}"/>  

                            /
  <h:outputText value="#{userObj.lastName}"></h:outputText>

  &nbsp;
   <h:outputText value="#{userObj.firstName}"></h:outputText>
  </p:column>

    <f:facet name="footer">  
     <p:commandButton id="addProjectUser" value=" Add " onclick="dlg1.show()" />  
      <p:commandButton id="deleteProjectUser" value=" Delete " />  

    </f:facet> 

</p:dataTable>

Managed Bean :

 @ManagedBean
 @SessionScoped
 public class ProjectAdminisrationMB implements Serializable {

private static final long serialVersionUID = 1L;

private String projectName;
private List <User> projectUsersList;
private List<User> projectNoUsersList;
private List<User> selectedUsers;

private String projectAdmin;


public ProjectAdminisrationMB() {
    super();
    AdministrationProjectFinal administrationProjectFinal =new    
             AdministrationProjectFinal();
    this.projectUsersList=administrationProjectFinal.getUserList();
    this.projectNoUsersList=administrationProjectFinal.getNotUserList();
}



public String getProjectName() {
    return projectName;
}

public void setProjectName(String projectName) {
    this.projectName = projectName;
}



public List<User> getProjectUsersList() {
    return projectUsersList;
}



public void setProjectUsersList(List<User> projectUsersList) {
    this.projectUsersList = projectUsersList;
}



public String getProjectAdmin() {
    return projectAdmin;
}

public void setProjectAdmin(String projectAdmin) {
    this.projectAdmin = projectAdmin;
}

public List<User> getProjectNoUsersList() {
    return projectNoUsersList;
}



public void setProjectNoUsersList(List<User> projectNoUsersList) {
    this.projectNoUsersList = projectNoUsersList;
}



public List<User> getSelectedUsers() {
    return selectedUsers;
}



public void setSelectedUsers(List<User> selectedUsers) {
    this.selectedUsers = selectedUsers;
}




 }

i'm getting this error:

  javax.faces.FacesException: DataModel must implement     
  org.primefaces.model.SelectableDataModel when selection is enabled.....
Amira
  • 3,184
  • 13
  • 60
  • 95
  • 1
    Tutorial link is dead. The working link is: https://www.primefaces.org/showcase/ui/data/datatable/selection.xhtml – KiriSakow Nov 27 '17 at 18:45
  • Possible duplicate of [DataModel must implement org.primefaces.model.SelectableDataModel when selection is enabled](https://stackoverflow.com/questions/10513873/datamodel-must-implement-org-primefaces-model-selectabledatamodel-when-selection) – Cœur Mar 12 '18 at 02:23

4 Answers4

87

just add this attribute rowKey to the datatable tag :

<p:dataTable border="1" value="#{projectAdminisrationMB.projectNoUsersList}" 
 var="userObj"
 rowKey="#{userObj.name}"selection="#{projectAdminisrationMB.selectedUsers}"
 selectionMode="multiple" rowIndexVar="rowIndex"
 binding="#{table2}">
Amira Manai
  • 2,599
  • 8
  • 40
  • 60
  • 22
    The value for the rowKey attribute need to be unique for each row and this cannot be null in any row. It can be a mix of several values e.g: `rowKey="#{userObj.id}-#{userObj.name}"` – John Alexander Betts Oct 17 '13 at 15:33
  • 2
    Since I had some columns with filtering, I found a solution adding also a value for the attribute `filteredValue` pointing it to a list of the same type of objects. – Izerlotti Oct 27 '16 at 12:56
  • 3
    @Izerlotti Your comment solved the problem in my case. I'd just like to make it clear for next strangers: when you filter datatable and it is at some moment rerendered (you change tabs or smth), you need to have a `List` of datatable items in your bean and you need to have it set in `filteredValue` attribute of your table. Elsewhere you'll get `DataModel must implement org.primefaces.model.SelectableDataModel` exception, that's a bit confusing. – ba3a Jul 04 '17 at 07:59
19

You can get this error if you try to add a new item to the underlying list and forget to assign a value to that new item's rowKey.

Nublodeveloper
  • 1,301
  • 13
  • 20
  • I have this exact problem, created a list and I added an object to it, and I'm having this error, what do you mean by assigning a value to that new item's rowKey? Can you give an example? @Nublodeveloper – user3672700 Aug 24 '21 at 19:40
  • 1
    @user3672700 Wow.. 2013 since I wrote the answer. Say rowKey is set to a field of a table... and you add a new row to that table... and forget to set the value of that field. The value of that field when that row is loaded/read into the table, cannot be null. – Nublodeveloper Aug 25 '21 at 20:28
5

Alternatively to rowKey you can wrap your data in a custom model which really implements org.primefaces.model.SelectableDataModel. This is helpful if

  • all of your your classes have the same kind of @Id (e.g. a long) and can implement the same interface (e.g. EjbWithId)
  • you want to add additional functionalities to your data which are not domain specific and don't belong e.g. User.

The interface may be something like this:

public interface EjbWithId
{
  public long getId();
  public void setId(long id);
}

Then a generic implementation of SelectableDataModel for all your classes can be used:

public class PrimefacesEjbIdDataModel <T extends EjbWithId>
       extends ListDataModel<T> implements SelectableDataModel<T>
{    
  public PrimefacesEjbIdDataModel(List<T> data)
  {  
    super(data);
  }  

  @Override public T getRowData(String rowKey)
  {  
    List<T> list = (List<T>) getWrappedData();  

    for(T ejb : list)
    {  
      if(ejb.getId()==(new Integer(rowKey))){return ejb;}  
    }
    return null;  
  }  

  @Override public Object getRowKey(T item) {return item.getId();}
}

In your @ManagedBean:

private PrimefacesEjbIdDataModel<User> dmUser; //+getter
dmUser = new PrimefacesEjbIdDataModel<User>(administrationProjectFinal.getUserList());
Thor
  • 6,607
  • 13
  • 62
  • 96
2

first check whether you've added rowKey="#{userObj.id}"

then you need to have the data table List set in filteredValue attribute of your data table in xhtml, instead of value.