JSF’s <h:dataTable> vs <ui:repeat> – How to get the selected row.
LincolnSo, a little while ago I was attempting to use JSF’s Facelets <ui:repeat> tag, as a replacement for <h:dataTable>, but difficulty came when I needed to process actions on individual records of each row.
<ui:repeat> allows iteration over a List of Array[] of items, but it does not provide a method of discovering the “selected” or “actioned” row; there’s no way to discover the row the user is interacting with. Or is there?
I’ve since learned of two ways to deal with this situation:
1. Use ListDataModel
I asked another JSF Expert, Dan Allen (author of Seam in Action) and here’s what he told me:
Lincoln,
There is an approach which will work in this case, but it doesn’t rule out the possibility that refinement is needed. Let me open with the example.
On the home page, there is a link that will load a feature list and navigate to the list page.
/home.xhtml
/list.xhtml
And finally, the controller:
@ManagedBean @SessionScoped // chosen for convenience, really it should be view-scoped or conversation-scoped (299) public class FeatureList { private DataModel features; public DataModel getFeatures() { return features; } public String load() { List l = new ArrayList(); l.add(new Feature("One")); l.add(new Feature("Two")); features = new ListDataModel(l); } public void action() { System.out.println("You clicked on the button in the row with feature " + ((Feature) features.getRowData()).getName()); } }
Note that the getRowData() method is positioned at the row which received the action during the invocation of any listener. Be careful, though, because it points to the first row if no row is selected. First check if getRowIndex() >= 0 to see if a row received an action.
Regardless, this is still a horrible way (IMO) of having to select the row. It is very opaque. This is one area where you really take Seam for granted because you would instead use injection of the selected row:
@DataModelSelection Feature selectedFeature;There may be some edge cases where this doesn’t work. Apply to your use case and report back any gaps.
-Dan
From Dan’s email, I learned that you could place a List of objects in a ListDataModel wrapper, effectively binding the state of the list to the UI. With that done, you can manipulate the data in an action-method, being able to retrieve the selected row index, object itself, and continue as you would expect with your programming.
2. Upgrade to an advanced EL (EL2) Jar
Probably my favorite solution – you can use EL2 method invocation, provided either by Seam, or Sun’s reference implementation, and pass the desired objects directly to methods in your JSP/Facelet code. It’s coming standard in J2EE 6, but why wait?
This method is simple, intuitive, and enables much more powerful and reusable Beans to handle page code, reducing redundancy in Model classes and business logic.
Note how I pass the current var object directly to the method via EL:
<h:commandButton id="add" value="Add Task" action="#{itemController.addItemNote(currentItemBean.item, addNoteBean.newNote)}">
And here’s the Backing Bean code:
@ManagedBean @RequestScoped public class ItemController { public String addTask(final Item item, final Note note) { ItemService.addNote(item, note); return "pretty:viewItem"; // this return statement is a PrettyFaces JSF bookmarking navigation id }
For instructions on how to: include EL2 in a JSF project go here.
For more information on JSF SEO and Bookmarking, take a look at PrettyFaces: URL rewriting extension for JSF.
If you are at all confused by these examples, feel free to leave a comment, and I’ll do my best to help.
![]() | About the author:Lincoln Baxter, III is a Senior Software Engineer at Red Hat, Inc., working on JBoss open-source projects. This blog represents his personal thoughts and perspectives, not necessarily those of his employer. He is a founder of OcpSoft, the author of PrettyFaces: bookmarking, SEO extensions for JSF, and an individual member of the JavaServer™ Faces Expert Group. When he is not swimming, running, or playing Ultimate Frisbee, Lincoln is focused on promoting open-source software and making web-applications more accessible for small businesses, individuals. His latest project is ScrumShark, an open-source, agile project management tool. |
Posted in JSF


I’ve been craving to be able to just pass a parameter into action methods!
Since I can’t use Seam I’ve been using
It leads to a setProp(someval) prior to invocation of the action method.
Anyway I know passing parameters is possible in Seam, but can’t find any references to it in J2EE6, or to “advanced EL2″ outside of Seam. Can you provide any URLs for more info on the standard (non-seam) implementations of this?
thanks!
oops some markup was removed from previous post. That should have been:
<f:setPropertyActionListener target="#{bean.prop}" value="someval" />
I’ve added the Maven repository and artifactId for each implementation, hope this helps.
I am trying to implement suggestion box in ui repeat. First suggestionBox works fine as expected:
a) somehow when I use the same in ui repeat suggestionAction event is not fired..
b) Sugeestion box uses id to display its content, problem is when user clicks “Add More regs” new row is added and id needs to be changed, please suggest how can handle dynamic ids to render suggestion box value as in code below.
<rich:suggestionbox id="suggestionBoxId" for="text" tokens=",[]"
…
We are using jboss4.2.3 and richfaces 3.3.1, jdk5
Please give your valuable inputs it will be very helpful.
XHTML
//THIS WORKS FINE
…
//NOT WORKING, SUGGESTIONACTION EVENT IS NOT FIRED
….
Save…
Do you know if the syntax for the advanced features in JBoss EL and the new Sun EL 2.1.2 in J2EE 6 / Glassfish 3 are completely compatible? That is, is either jar a drop-in replacement for the other?
Thanks.
They are mostly the same, if I am not mistaken! Though Seam EL may provide some additional functions off of the List type.
Hi Lincoln,
I have problem in datatable of jsf. i want to create dynamic data. my complete data in a double array you can suppose.
like
private Set bundleColumns;
:-complete column so i can figure out how many rows will need to populated.
Map<rowId here,Map> bundleMap;
so how i can draw on server side please let me know. i also try few examples but did not get any solution. its urgent please reply me. my id is ved.java@gmail.com
Ved,
I’m not sure what you are asking.
Could you please give an example of what you’re trying to do?
Hi Lincoln, can we have something like highlite aparticular row in a datatable?