An Introduction To JBoss RichFaces
Specific row update
Updating the whole table is rather simple. How do we update only the row that has been edited? All data components in RichFaces (including a4j:repeat) come with a feature that allows updating only a subset of rows. All such components expose an ajaxKeys attribute that points to the row or rows that need to be updated.
Let's first go over the changes we need to make on the page.
First, we need to set the ajaxKeys attribute on rich:dataTable (changes shown in bold):
<rich:dataTable value="#{userBean.users}" var="user"
ajaxKeys="#{userBean.rowsToUpdate}">That's all we need to do with the table.
Next we need to call a save method from the modal panel when we make changes to the user information. The updated Save link will look like this:
<a4j:commandLink actionListener="#{userBean.save}"
oncomplete="#{rich:component('useredit')}.hide()"
reRender="name, email">
Save
</a4j:commandLink>
The actionListener points to a listener inside the managed bean which we are going to create next. We also have the reRender attribute pointing to columns in the table. Basically, to achieve partial table update, we need to specify two things. First, which columns to update. In our case we are updating the name and email columns. Second, we need to specify which rows to update. This is done via the ajaxKeys attribute which is bound to a Set object that holds row numbers to update.
Let's see what changes are need in the managed bean.
First, we need to create the Set object to hold rows to update:
private Set <Integer>rowsToUpdate;
public Set <Integer>getRowsToUpdate() {
return rowsToUpdate;
}
Only a getter is needed for this property as this property will never be set from the page.
Next, we need the save() listener.
public void save (ActionEvent event) {
rowsToUpdate.clear();
rowsToUpdate.add(users.indexOf(selectedUser));
}
In the save listener, all we need is to save the row number of the user we are editing.
Finally, we need to initialize rowsToUpdate property inside the init() method, right after we create the users:
rowsToUpdate = new HashSet<Integer>();
The only other change we need is to add an a4j:keepAlive tag to the page. This is poor's man conversation scope (like in Seam). Basically, we need to keep the list of users alive for longer than a request and so a4j:keepAlive does just that. Right before the modal panel, add the following:
<a4j:keepAlive beanName="userBean"/>
Make sure everything is saved, redeploy, and run the application. You should now be able to open a modal panel, edit user information, and save the changes. When the changes are saved, only that particular row is updated.
Summary
I'm hoping this example showed you a little bit more than just Hello World. We have used a table component together with a modal panel. These are two components that very often used in real applications. I have also showed you how to edit a particular record inside a table via the modal panel and then only update that particular row. Of course, updating just a specific row is a feature of RichFaces data components.
To point out another thing, when we created an AJAX-based application here, we didn't have to deal with any JavaScript (well, besides the very simple client-side function available in RichFaces). RichFaces takes care of generating all the necessary (and usually quite complicated) JavaScript.
With RichFaces, you can continue using a JSF component-based approach, but with a large set of extra components to build applications with a rich user interface.
About the Author
Max Katz is a Senior Systems Engineer at Exadel. He has been helping customers jump-start their RIA development as well as providing mentoring, consulting, and training. Max is a recognized subject matter expert in the JSF developer community. He has provided JSF/RichFaces training for the past three years, presented at many conferences, and written several published articles on JSF-related topics. Max also leads Exadel's RIA strategy and writes about RIA technologies in his blog, http://mkblog.exadel.com. He is an author of Practical RichFaces book (Apress). Max holds a BS in computer science from the University of California, Davis.
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)






Comments
Max Katz replied on Mon, 2009/02/16 - 9:48pm
in response to:
Harshad Khasnis
Max Katz replied on Mon, 2009/02/16 - 9:51pm
in response to:
Asma Shah
nancy xiao replied on Mon, 2009/02/16 - 10:24pm
nancy xiao replied on Mon, 2009/02/16 - 10:24pm
nancy xiao replied on Mon, 2009/02/16 - 10:24pm
Thai Dang Vu replied on Sat, 2009/02/21 - 7:20am
I have a question:
Your "Save" link is in the form in the modal panel and it's going to re-render the columns "name" and "email" which are in another form. How can RichFaces know which form that has the "name" and "email" columns to re-render?
Max Katz replied on Mon, 2009/02/23 - 5:44pm
in response to:
Thai Dang Vu
It first searches the current naming container (form), then it searches the parent container and so on. At some point it will reach the root and search from there.
You can see the full algorithm here: org.ajax4jsf.renderkit.RendererUtils.findComponentFor(UIComponent, String)
Tom Schurmans replied on Wed, 2009/03/04 - 5:56am
Unexpected error processing managed bean userBean com.sun.faces.mgbean.ManagedBeanPreProcessingException: Unexpected error processing managed bean userBean at com.sun.faces.mgbean.BeanManager.preProcessBean(BeanManager.java:356) at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:201) ...
Caused by: com.sun.faces.mgbean.ManagedBeanPreProcessingException: Unexpected error processing managed property users ...
Caused by: java.lang.NullPointerException at com.sun.faces.mgbean.ManagedBeanBuilder.bakeBeanProperty(ManagedBeanBuilder.java:350) at com.sun.faces.mgbean.ManagedBeanBuilder.bake(ManagedBeanBuilder.java:107) ... 59 more
Any thoughts?
btw, the zip file you included doesn't work here. And the alternative doesn't give the extra "jsf + richfaces option" when you start a new eclipse project. Any chance you can rezip it and upload it somewhere else?
Thanks!
Max Katz replied on Sat, 2009/03/07 - 12:45am
in response to:
Tom Schurmans
@TomSch: You might have an error in Faces config file, can you post it here? As for the zip file, I'll try to upload a new or post a link on my blog.
Jean Chastain replied on Fri, 2009/03/20 - 9:27am
in response to:
Max Katz
Max, I know you're a busy guy, but I want to pick up this thread. I'm running on JBoss 5.0 and have the same problem shahasma99 is having. After the first deploy (before the modal panel is added), all I see it the title. I do have the @PostConstruct before the init(), but when I set a breakpoint on the init(), it doesn't seem to be getting there. Is there some JBoss configuration I'm missing? Or is it just not possible to break there?
TIA, Jean
Kannan Varadharajan replied on Fri, 2009/04/03 - 7:48am
Alex Cbbdjfkdjfkj replied on Fri, 2009/04/03 - 10:26am
Max Katz replied on Thu, 2009/04/09 - 10:32pm
in response to:
Jean Chastain
Max Katz replied on Thu, 2009/04/09 - 10:32pm
in response to:
Kannan Varadharajan
Max Katz replied on Thu, 2009/04/09 - 10:34pm
in response to:
Alex Cbbdjfkdjfkj
Davut Uysal replied on Fri, 2009/04/17 - 2:21am
Nghia Le replied on Mon, 2009/04/27 - 3:41pm
Nick Thomson replied on Thu, 2009/04/30 - 9:36am
Hi Maxkatz,
I'm trying to use the ajaxKeys options with a dataTable as you have described in the article and I've got it working with the dataTable and even using the dataScroller control.
However, once I enable sorting in the data table, the rows do not refresh properly. If the items are sorted in the same order as they are in the List the correct rows are redrawn, but sorting them in any other order results in the required rows not being highlighted.
I'm using Seam 2.1.1.GA and RichFaces 3.3.0.GA, the table looks like this (the keepalive is included but not shown and I've removed some of the columns)..
<rich:dataTable id="testDataTable" value="#{testBean.data}" var="data" ajaxKeys="#{testBean.ajaxKeys}" sortMode="single" rows="20">
<rich:column sortBy="#{data.id}" id="pid" style="#{data.viewing ? 'background: red' : '' }">
<f:facet name="header">
<h:outputText value="ID"/>
</f:facet>
<a4j:commandLink style="display: block; width: 100%;" action="#{testBean.SelectView(data)}" value="#{data.id}" reRender="pid,param1"/>
</rich:column>
<rich:column sortBy="#{data.testParam1}" id="param1" style="#{data.viewing ? 'background: red' : '' }">
<f:facet name="header">
<h:outputText value="Param 1"/>
</f:facet>
<a4j:commandLink style="display: block; width: 100%;" action="#{testBean.SelectView(data)}" value="#{data.testParam1}" reRender="pid,param1"/>
</rich:column>
</rich:dataTable>
And the appropriate bits from the testBean..
Any idea how to fix this?
Thanks,
Nick
Alex Cbbdjfkdjfkj replied on Tue, 2009/05/05 - 9:53am
For those having difficulty (like me!) with the step that says "For JSF environment, select JSF 1.2, Facelets, RichFaces", try this:
- After downloading the template zip file, DON'T just copy and paste the folders into the jboss template folder!
- Copy the richfaces-template-6.zip\lib\jsf-1.2-facelets-richfaces\ to your Eclipse's appropriate folder (for me, it's here: C:\eclipse_ide\plugins\org.jboss.tools.common.projecttemplates_3.0.0.GA-R200903141626-H5\lib)
- Copy the \templates\jsf-1.2-facelets-richfaces\ to your Eclipse folder (something like C:\eclipse_ide\plugins\org.jboss.tools.common.projecttemplates_3.0.0.GA-R200903141626-H5\templates)
- And don't forget the \templates\pages\jsf\
- In other words, you need to go into each downloaded item and copy its contents over to the matching folder on your jboss installation.
If you don't see the RichFaces item in the Eclipse dropdown, then you didn't copy the items over correctly. Try again. Believe it or not, this step messed me up! I finally see that item in the dropdown box and can proceed with the tutorial!Max Katz replied on Tue, 2009/05/05 - 12:13pm
in response to:
Davut Uysal
Max Katz replied on Tue, 2009/05/05 - 12:15pm
in response to:
Nghia Le
Max Katz replied on Tue, 2009/05/05 - 12:18pm
in response to:
Nick Thomson
Max Katz replied on Tue, 2009/05/05 - 12:20pm
Davut Uysal replied on Wed, 2009/05/06 - 12:57pm
in response to:
Max Katz
Debraj Ganguly replied on Sat, 2009/05/09 - 7:56am
I have a page which has a link to open a modal panel (BasePage.jsp)
h:form
..............
..............
a href="#" onclick="#{rich:component(modal_panel)}.show()">#{msg.ShowPanel}/a
...........
.........
/h:form
I am including the modal panel page in the base page after this in a separate form
h:form
ui:include src="MyModalPanel.jsp" /
h:form
MyModalPanel.jsp
----------------------
In this page I have a tab containing a number of and elements.
I also have a a4j:commandButton at the end. I have an action defined for the button.
a4j:commandButton id="save_form" value="Save" image="../../images/Save_bttn.jpg"
action="#{baseBean.save}" reRender="validation_messages_add" ajaxSingle="false" /
I am reRendering the validation message.
My problem
--------------
on clicking the save button the baseBean.save() method is called correctly but the bean is not getting reflected with the user entered value. It still hold the initialized values that i had in the base bean attrib definition.
I changed the a4j:commandButton to h:commandButton and also added the onclick function to hide the modal. I had no problem then but this closed the modal panel and the validation messages on the panle could not be viewed by the user.(page refreshed.)
Can you please guide me why the a4j:commandButton thing is unable to get the form values.
waiting for your reply,
thanks in advance
(I have purposefully ommited the '<' and '>' tags
Annie Cheng replied on Thu, 2009/05/14 - 11:20am
Max Katz replied on Tue, 2009/05/19 - 5:45pm
in response to:
Debraj Ganguly
Sorry, I don't understand the problem. Where is the input field? I'm also surpised that this works, that's JSP with Facelets...:
<ui:include src="MyModalPanel.jsp" />
Max Katz replied on Tue, 2009/05/19 - 5:46pm
in response to:
Annie Cheng
hookfi john replied on Sun, 2009/05/31 - 7:48am
jame jack replied on Mon, 2009/06/29 - 4:23pm