I just started learning JSF and PrimeFaces, and I'm having a hard time trying to get PrimeFaces' datatable to work. I have a checkbox-based selection mechanism (more than one row can be selected at the same time), so that clicking on the "Delete selected users" button triggers a method call to the backing bean to delete the corresponding users from the database.
The problem is that the selected rows are not stored in the backing bean's selectedUsers
array, and I can't understand why, since my code is exactly the same as the one hosted on PrimeFaces' ShowCase. As a consequence, the button successfully triggers the confirmation dialog, but no user ever gets deleted from the system. Does anyone have any advice?
Thank you in advance!
xhtml file
<h:form id="tableForm">
<p:dataTable id="userList" var="user" value="#{userListBean.userList}"
selection="#{userListBean.selectedUsers}" rowKey="#{user.username}">
<f:facet name="header">User list</f:facet>
<p:column selectionMode="multiple" style="width:2%"/>
<!-- data columns here, working just fine -->
<f:facet name="footer">
<p:commandButton value="Delete selected users" icon="ui-icon-trash" action="#{userListBean.deleteSelectedUsers()}">
<p:confirm header="Deletion confirmation" message="Are you sure you want to delete #{fn:length(userListBean.selectedUsers)} users?" icon="ui-icon-alert" />
</p:commandButton>
Registered users: #{fn:length(userListBean.userList)}
</f:facet>
</p:dataTable>
<p:confirmDialog global="true" showEffect="fade">
<p:commandButton value="Yes" type="button" styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
<p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="ui-icon-close"/>
</p:confirmDialog>
</h:form>
Backing Bean (userMgr handles persistence on the server, it should have nothing to do with my issue)
@ManagedBean(name="userListBean")
@ViewScoped
public class UserListBean {
@EJB
private UserManager userMgr;
private List<UserDTO> userList;
private UserDTO[] selectedUsers;
public UserListBean() {
}
public void deleteSelectedUsers() {
for(UserDTO u : selectedUsers)
userMgr.deleteUser(u.getUsername());
setUserList(userMgr.retrieveAllUsersDTO());
}
public List<UserDTO> getUserList() {
if(userList == null)
setUserList(userMgr.retrieveAllUsersDTO());
return userList;
}
public void setUserList(List<UserDTO> userList) {
this.userList = userList;
}
public List<UserDTO> retrieveUserList() {
return userMgr.retrieveAllUsersDTO();
}
public UserDTO[] getSelectedUsers() {
return selectedUsers;
}
public void setSelectedUsers(UserDTO[] selectedUsers) {
this.selectedUsers = selectedUsers;
}
}
(As a side question: the #{fn:length(userListBean.selectedUsers)}
EL expression always returns 0. I used to think it was because of the broken selection mechanism, but could it be because the array is still empty when the confirmation dialog is rendered?)
org.primefaces.model.LazyDataModel<T>
should be preferable, in this case. A view scoped bean must implement thejava.io.Serializable
interface. - TinygetUserList
into a method annotated with@PostConstruct
. Then yourgetUserList
should do only what it says: getsuserList
- kolossus