Skip to main content

ui:repeat and Ajax

Posted by driscoll on August 17, 2009 at 2:35 PM PDT

A nice feature of Facelets is the ui:repeat tag, which iterates over a supplied list of values to do a full list on your page. One problem: it'll add an index to the generated id's, which can make using it with Ajax a bit of a drag. But if you're just using the f:ajax tag, that index is detected automatically, making ajaxifying the tag relatively easy. Here's a quick example:


Say you want to make a page that offers three drop down menus with three choices each (it's a simple example, work with me here). Here's the data structure, set up as a bean:


   1 package demo;
   2
   3 import java.util.ArrayList;
   4 import java.util.Arrays;
   5 import java.util.List;
   6 import javax.faces.bean.ManagedBean;
   7
   8 @ManagedBean
   9 public class RepeatBean {
  10
  11     private String[] sarray = {"one", "two", "three"};
  12     private String[] sarray2 = {"four", "five", "six"};
  13     private String[] sarray3 = {"seven", "eight", "nine"};
  14
  15     private List<List<String>> llist;
  16
  17     private String[] resultArray = {"two", "four", "nine"};
  18
  19     public RepeatBean() {
  20         List<String> slist = Arrays.asList(sarray);
  21         List<String> slist2 = Arrays.asList(sarray2);
  22         List<String> slist3 = Arrays.asList(sarray3);
  23
  24         llist = new ArrayList<List<String>>();
  25         llist.add(slist);
  26         llist.add(slist2);
  27         llist.add(slist3);
  28
  29     }
  30     public List<List<String>> getLlist() {
  31         return llist;
  32     }
  33     public String[] getResultArray() {
  34         return resultArray;
  35     }
  36     public String getResultArray(int i) {
  37         return resultArray[i];
  38     }
  39     public void setResultArray(int i, String value) {
  40         resultArray[i] = value;
  41     }
  42     public void setResultArray(String[] resultArray) {
  43         this.resultArray = resultArray;
  44     }
  45 }

We create three lists - they'll be the content of the drop down menus. We then create a list of String lists - llist - we'll use this as the input for the . We also make a list to hold the results: resultArray.

Now: to use it in a page:


   1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   2 <html xmlns="http://www.w3.org/1999/xhtml"
   3       xmlns:ui="http://java.sun.com/jsf/facelets"
   4       xmlns:h="http://java.sun.com/jsf/html"
   5       xmlns:f="http://java.sun.com/jsf/core"
   6       xmlns:c="http://java.sun.com/jsp/jstl/core">
   7     <h:head>
   8         <title>Repeat Test Demo</title>
   9     </h:head>
  10     <h:body>
  11
  12         <h:form id="repeatForm">
  13             <ui:repeat value="#{repeatBean.llist}" var="list" varStatus="current" id="repeat">
  14                 <h:selectOneMenu value="#{repeatBean.resultArray[current.index]}" id="chooseOne">
  15                     <f:selectItems value="#{list}"/>
  16                     <f:ajax render="outText"/>
  17                 </h:selectOneMenu>
  18                 <h:outputText value="#{repeatBean.resultArray[current.index]}" id="outText"/>
  19                 <br/>
  20             </ui:repeat>
  21         </h:form>
  22     </h:body>
  23 </html>

This ends up generating ids for the outputText field that look like: repeatForm:repeat:2:outText. But because we're using the f:ajax tag, we only need to specify "outText" - the tag takes care of the work of finding out what the real id is.


Neat, huh? In case you're not familiar with the ui:repeat tag - you should take a minute to get familiar with it, it's core Facelets functionality. By using the var value, we're saying that we want to create a list variable that will contain one of the lists in llist every iteration. By using varStatus and the index property, we're keeping track of all of the values selected.


Just a simple example of the use of the f:ajax tag in a complex rendered environment. As always, let me know if you have any questions.

Related Topics >>

Comments

I wonder why fo you list 36

I wonder why fo you list
36 public String getResultArray(int i) { 37 return resultArray[i]; 38 } 39 public void setResultArray(int i, String value) { 40 resultArray[i] = value; 41 }
I don't think these may be called from JSF EL expressions, right?
I guess, even
42 public void setResultArray(String[] resultArray) { 43 this.resultArray = resultArray; 44 }
is not needed, it's not called by JSF, it's String[] getResultArray() which does all the tricks. (even though repeatBean.resultArray cannot be used as lvalue, repeatBean.resultArray[current.index] can.
-----
Also, can you please comment on this ":" logic in ids specified in f:ajax? It looks sometimes :out makes sence or is it for the cases when prependId=false? Is there a set of rules somewhere which tell how those ids are resolved? (one cannot start with form: in a compositeComponent, so there should be a way to use local ids)
(My original problem is that I'm trying to ajaxify a composite component which has ui:repeats and a lot of panel group render="..." which as I heard adds even more tricks...)

UIComponent.findComponent has the rules

The rules you are looking for are found in the JavaDoc for UIComponent.findComponent.

They're not especially simple, but they are useful - which is the point of this blog posting.

prependId doesn't effect their interpretation - and a leading ":" means to just look for that id in the tree. So, ":out" will look for the toplevel component that has an id of "out". Even it's nested in a form with prependId=false, if the form id is "form", then the id you are looking for will still be ":form:out".

Getting dynamic ids ui repeat - Please give your valuable inputs

Good article... Please give your valuable inputs it will be very helpful. 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. ... We are using jboss4.2.3 and richfaces 3.3.1, jdk5 Which version have f:ajax? XHTML: //THIS WORKS FINE ... //NOT WORKING, SUGGESTIONACTION EVENT IS NOT FIRED .... Save...

Hi Jim! Is there a way to

Hi Jim! Is there a way to specify the row(s) index you want to update, not only the active row?

Just use the ID

Rather than give you the answer, let me describe how to get the answer: Check the rendered ID - it's the attribute ID in the rendered row. You would then use that, possibly with a leading ":" if you are using the ajax tag, or just the straight ID, if you are using the JavaScript Ajax function.

That's not JSF 2

This blog entry is about JSF 2. The stuff you're working with is not JSF 2 - in fact, it's my understanding that RichFaces 3 doesn't work with JSF 2, and that they're working on RichFaces 4 to overcome that - but you'll need to check in with folks who work with RichFaces for more information - as well as the answer to your question.