Partial update of data iteration components

The simplest way to update a data iteration component (for example, a rich:dataTable) is to re-render the entire table even if just one row was changed.

There is a more powerful way to optimize this process and it is the capability to choose which rows have to be updated during the re-rendering of the list. The good news is that this is a quite simple task and we are going to see it now.

First of all, let's create a rich:dataTable table. We are going to re-use the GroupsListHelper Seam component to get the list of the groups to fill in the table.

Let's create the /view/examples/partialUpdate/partialUpdateExample.xhtml file:

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:rich="http://richfaces.org/rich"
xmlns:a="http://richfaces.org/a4j"
template="/layout/template.xhtml">
<ui:define name="body">
<h:panelGrid columns="2">
<h:form>
<rich:dataTable
value="#{groupsListHelper.groups}"
var="group">
<f:facet name="header">Groups renamer</f:facet>
<rich:column>
<f:facet name="header">Name</f:facet>
<h:outputText value="#{group.name}"/>
</rich:column>
</rich:dataTable>
</h:form>
</h:panelGrid>
</ui:define>
</ui:composition>

That's very simple to understand it's just a rich:dataList showing the names of the groups that we have in the database.

Now we want to put an Edit link button for every group to make it appear as a panel on the right side of the page, which is used to edit the selected group. After clicking on the Save button, the panel disappears and only the edited table row is updated.

Let's edit the rich:column inside the rich:dataTable; it might look like this:

<rich:column>
<f:facet name="header">Name</f:facet>
<h:panelGroup id="groupRow">
<h:outputText value="#{group.name}"/>
<h:panelGroup rendered="#{group.id!=partialUpdateExampleHelper. selectedGroup.id}">
(<a:commandLink value="Edit" reRender="groupRow"
action="#{partialUpdateExampleHelper. editGroup(group)}"/>)
</h:panelGroup>
</h:panelGroup>
</rich:column>

We have just added and enclosed h:panelGroup with the id set as groupRow (we'll see later where we are going to use it) and the a:commandLink component that initiates the editing of the group at that row.

Now, let's add another attribute to the rich:dataTable component called ajaxKeys:

ajaxKeys="#{partialUpdateExampleHelper.ajaxUpdateRows}"

You can use this attribute to every data iteration component and it points to an array containing a list of row numbers of the rows that have to be updated.

Also, let's add the edit panel after the closing</h:form> tag:

<a:outputPanel ajaxRendered="true">
<h:form rendered="#{partialUpdateExampleHelper.selectedGroup.id!=null}">
<rich:panel>
<f:facet name="header">
Edit #{partialUpdateExampleHelper.selectedGroup.name} group
</f:facet>
<h:inputText id="groupName" value="#{partialUpdateExampleHelper.selectedGroup.name}"/>
<a:commandButton value="Save" reRender="groupRow"
process="groupName"
action="#{partialUpdateExampleHelper.saveSelectedGroup}"/>
<a:commandButton value="Cancel"
reRender="groupRow"
ajaxSingle="true"
action="#{partialUpdateExampleHelper.cancelGroupEditing}"/>
</rich:panel>
</h:form>
</a:outputPanel>

We have enclosed everything inside a:outputPanel with the ajaxRendered attribute set to true, so that we don't have to explicitly re-ender it at every request (it is done automatically at every Ajax request). We can notice that the edit form is rendered only if there is a group selected.

You can also see that when the form is submitted (by clicking on Save button), we are re-rendering h:panelGroup inside the column and not the whole table.

Let's use the backing bean to manage the partial update. Let's create the Java class book.richfaces.advcm.modules.main.examples.partialUpdate.PartialUpdateExampleHelper; it might look like this:

package book.richfaces.advcm.modules.main.examples.partialUpdate;
@Name("partialUpdateExampleHelper")
@Scope(ScopeType.CONVERSATION)
public class PartialUpdateExampleHelper {
@In(create = true)
EntityManager entityManager;
@In(create = true)
GroupsListHelper groupsListHelper;
private Set<Integer> ajaxUpdateRows;
private ContactGroup selectedGroup;
public void editGroup(ContactGroup group) {
setSelectedGroup(group);
// Tell RichFaces to reRender just the selected row
reRenderRow();
}
public void cancelGroupEditing() {
// Tell RichFaces to reRender just the selected row
reRenderRow();
// Empty the selected group
setSelectedGroup(null);
}
public void saveSelectedGroup() {
// Save the group data to database
entityManager.merge(getSelectedGroup());
// Tell RichFaces to reRender just the selected row
reRenderRow();
// This group is no more selected
setSelectedGroup(null);
}
private void reRenderRow() {
// We have to clear the list of elements to reRender
// because this component scope is conversation
getAjaxUpdateRows().clear();
// Find the index of the selected group inside the
// groups list
int groupIndex = groupsListHelper.getGroups(). indexOf(getSelectedGroup());
// Tell to RichFaces to reRender just this row
getAjaxUpdateRows().add(groupIndex); }
public Set<Integer> getAjaxUpdateRows() {
if (ajaxUpdateRows == null) {
ajaxUpdateRows = new HashSet<Integer>();
}
data iteration componentpartial updationreturn ajaxUpdateRows;
}
public void setAjaxUpdateRows(Set<Integer> ajaxUpdateRows)
{
this.ajaxUpdateRows = ajaxUpdateRows;
}
public ContactGroup getSelectedGroup() {
return selectedGroup;
}
public void setSelectedGroup(ContactGroup selectedGroup) {
this.selectedGroup = selectedGroup;
}
}

After the injection of the entityManager component (used to merge the modified data submitted by the edit form) and the groupListHelper component (used to get the groups list shown into the dataTable), we can find two properties. The first one (ajaxUpdateRows) contains, as we've said, the list of the indexes of the groups list that has to be re-rendered (in our case only one row) and, the second one contains the pointer to the group that is being edited (if null, no groups are being edited). We can find the getter and setter for every property at the end of the class. In the middle, we see three methods called by the XHTML code that are used to start group editing (editGroup), cancel the editing of the selected group (cancelEditingGroup), and save the newly edited group data (saveSelectedGroup).

We can notice that every method clears and then adds the selected group row index in the ajaxUpdateRows list, to tell the rich:dataTable component to only re-render that row.

In order to do that, they call the reRenderRow method that clears the list of elements to re-render (we have to do that because the component has CONVERSATION scope and the list is kept for every request), and then, find the index of the selected group from the list of groups (inside the groupsListHelper bean).

The last task to do is to add a partialUpdateExample.page.xml file to begin the conversation when the page is accessed.

Here is the screenshot of the preceding example in Edit mode:

Partial update of data iteration components
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.106.33