Reputation: 19314
I'm using primefaces 4.0 datatable using a LazyDataModel. I'm also using the <p:rowEditor />
and when a row is edited and saved, my datatable data is not being updated. It seems that the LazyDataModel.load method is not called on an ajax update.
Is there something I'm doing wrong or a workaround? Is this a known problem?
LazyUserDataModel.java
public class LazyUserDataModel extends LazyDataModel<User> {
private static final long serialVersionUID = -7759670987463023731L;
private List<User> users;
private Dao dao;
private String username;
private List<String> roles;
public LazyUserDataModel(Dao dao, String username, List<String> roles) {
this.dao = dao;
this.username = username;
this.roles = roles;
}
@Override
public List<User> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,String> filters) {
List<User> users = new ArrayList<User>();
users = dao.findAllUsers(username, roles, first, pageSize);
...
UserGroupBacking.java
...
private LazyDataModel<User> users;
@PostConstruct
public void init() {
this.ds = databaseBacking.getDs();
if(isLoggedIn()) {
loadData();
}
}
public void updateUsersGroups(RowEditEvent event) {
// Save data to db (this part works fine)
loadData();
}
private void loadData() {
Dao dao = new Dao(ds);
users = new LazyUserDataModel(dao, accessBacking.getUsername(), accessBacking.getRoles());
}
...
.xhtml
<p:tabView id="tabs">
<p:tab id="userTab" title="Users">
<h:form id="userForm">
<p:growl for="growl" severity="info" autoUpdate="true" showDetail="true" />
<p:messages id="userMessages" severity="error" showDetail="true" />
<p:dataTable var="user" value="#{userGroupBacking.users}" editable="true" id="userTable" paginator="true" rows="20"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}" lazy="true"
filteredValue="#{userGroupBacking.filteredUsers}" >
<p:ajax event="rowEdit" listener="#{userGroupBacking.updateUsersGroups}" update=":tabs:userForm:userTable, :tabs:userForm:userMessages" />
<p:column headerText="User" filterBy="#{user.name}" filterMatchMode="contains">
<h:outputText value="#{user.name}" />
</p:column>
<p:column headerText="Groups">
<p:cellEditor>
<f:facet name="output">
<ui:repeat var="group" value="#{user.groups}">
<h:outputText value="#{group.name}" /><br />
</ui:repeat>
</f:facet>
<f:facet name="input">
<p:selectCheckboxMenu value="#{user.groupsAsString}" label="Groups" filter="true" filterText="Filter" filterMatchMode="contains">
<f:selectItems value="#{userGroupBacking.groupsAsSelectItems}" />
</p:selectCheckboxMenu>
</f:facet>
</p:cellEditor>
</p:column>
...
Upvotes: 4
Views: 9252
Reputation: 1109570
It appears that the <p:ajax event="rowEdit">
does by design inside the table not update anything else than the edited row. Even not when explicitly specified by update
attribute. It'll be plain ignored. This makes maybe sense, but this is IMO too overzealous and worth an issue report.
I did some digging in the source code, but it appears not to be easily and nicely possible to change/override this behavior. Your best bet is to perform the update of the entire table in a separate ajax request. The <p:remoteCommand>
is helpful in this.
Instead of
<p:dataTable id="userTable" ...>
<p:ajax event="rowEdit" listener="#{userGroupBacking.updateUsersGroups}" update=":tabs:userForm:userTable, :tabs:userForm:userMessages" />
...
</p:dataTable>
do
<p:remoteCommand name="updateUsersGroups" action="#{userGroupBacking.updateUsersGroups}" update="userTable userMessages" />
<p:dataTable id="userTable" ...>
<p:ajax event="rowEdit" oncomplete="updateUsersGroups()" />
...
</p:dataTable>
and remove the RowEditEvent
argument from the method.
By the way, instead of recreating the whole LazyDataModel
in order to force a reload of the lazy data model, you could alternatively also just get a handle of DataTable
component instance in some way (as method argument?) and invoke loadLazyData()
method on it. E.g. via binding
:
<p:remoteCommand name="updateUsersGroups" action="#{userGroupBacking.updateUsersGroups(userTable)}" update="userTable userMessages" />
<p:dataTable id="userTable" binding="#{userTable}" ...>
<p:ajax event="rowEdit" oncomplete="updateUsersGroups()" />
...
</p:dataTable>
with
public void updateUsersGroups(DataTable table) {
// ...
table.loadLazyData();
}
Upvotes: 4