JSF’s <h:dataTable> vs <ui:repeat> – How to get the selected row.
So, 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:
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.
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.
Need some /pretty /urls in your JSF web-app? Try PrettyFaces: URL-rewriting for Java EE and JSF. (Free and open-source!)
And here’s the Backing Bean code:
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()); } } |
Lincoln’s note — In JSF2, you can call the isRowSelected() method, instead of this check.
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; |
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)}"> |
@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.
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?
Hi Lincoln,
Any comments/updates on how to selecting a row in a JSF dataTable? I need to provide the same functionality in a JSF table that I could provide with an onclick JavaScript event in HTML. I need to change the CSS when a table row is clicked.
Hi Lincoln,
I added EL2 to my project by downloading el-api and al-impl from the sources you mentioned in the respective link and copied them to WEB-INF/lib (I don’t use maven). Additionally, I added the given parameter entry to web.xml. In my xhtml file I added a button with
…
…
where row is an ArrayList. However, eclipse keeps telling me the “Syntax Error in EL”. What am I doing wrong? I was as well adding the two jar-files to the classpath libraries but same effect. I am using eclipse indigo with the JSF reference impl (mojarra) and glassfish 3.1.
Regards,
Mike
another try – this time without the pre-wrapper
Hi,
I’m using very easy solution:
Function portfolioTypeView.selectItem() set selectedItem atribute in class PortfolioTypeView.
It’s realy work.
Here is code:
I m working with seam framework,
I have a Table for eg. student (no, name)
& for that I created Seam Generated entity using wizard in eclipse.
which gives me an entity & a session file to manage data of student.
In my page I have taken a JSF dataTable, in that data table I m able to display the two columns no & name
But in addition I want to add check box for row selection and a button.
when I that button I want selected data !!
If you help me, I will b very thankful to you !!
Iam dynamically adding new rows in dataTable by clicking on AddRow button . While Iam doing Ajax call on each row for particular column the method was invoking but the values are not passing to backing bean why??