-
Notifications
You must be signed in to change notification settings - Fork 15
ForEach 2.x
TOCSTART
TOCEND
The ForEach component is an iterator component that renders the specified set of components
multiple times based on its parameters. The ForEach component is similar to the JSTL
<c:forEach> tag, though it can be used to overcome some of the shortcomings of
<c:forEach>
tag and to eliminate the need for an additional JSTL dependency.
- Iterating over a collection of objects
- Specifying iteration index range and step
- Wide range of supported collection types
The ForEach component is represented by the <o:forEach> tag with a set of child components and/or HTML markup. The content of the <o:forEach> tag will be rendered several times once for each iteration step according to the iteration parameters specified with <o:forEach> tag's attributes. Note that although ForEach is identical in API to the JSTL <c:forEach> tag, the <o:forEach> tag doesn't create several instances of iteration components as <c:forEach> does. Instead of this, the same child components are rendered several but with different parameters – once per each iteration step. Below are the descriptions of various kinds of iteration possible with the ForEach component.
The simplest and probably the most popular way of iteration is iterating over a collection of objects, the inner components of the <o:forEach> tag are rendered once for each object. Here's an example:
<o:forEach items="#{MyBean.tasks}" var="task" varStatus="status"> <h:outputText value="#{status.count}. #{task.name}"/> <br/> </o:forEach>
As you can see in this example, the collection of items can be specified using the items attribute, and this attribute should be declared as value binding to one of the following types:
- java.util.Collection (or any of its implementations);
- array;
- javax.faces.model.DataModel (or any of its implementations);
- java.sql.ResultSet;
- javax.servlet.jsp.jstl.sql.Result.
The ForEach component will render its content once for each item, and the rendered content can use the current item and current iteration step parameter variables specified with the following attributes:
- var attribute specifies the name of the variable referring to the currently rendered item, and
- varStatus attribute specifies the name of the variable referring to the current iteration status object.
The iteration status object is of type IterationStatus, and it provides the following information on the current iteration step:
- current property refers to the current item object.
- count is a number of the current round of iteration. The first round has a value of 1.
- first returns true if the current round of iteration is the first one, that is when the first item is being displayed.
- last returns true if the current round of iteration is the last one, that is when the last item is being displayed.
- begin defines the value of the <o:forEach> tag's begin attribute if specified, and null otherwise. This attribute will be described in the following two sections.
- end defines the value of the <o:forEach> tag's end attribute if specified, and null otherwise. This attribute will be described in the following two sections.
- step defines the value of the <o:forEach> tag's step attribute if specified, and null otherwise. This attribute attribute will be described in the following two sections.
- index defines the number corresponding to the current round of iteration. When iterating over a collection this number corresponds to an collection index of the currently displayed item. Unlike the count value value of index property depends on begin, end, and step attributes of the <o:forEach> tag.
The example above uses the count property for displaying the task number before task name.
This kind of iteration is actually an extension of the ordinary item iteration feature described above. It is possible to specify restrict the range of displayed items, display items in the reverse order, and specify the iteration step so that every n-th item be rendered. Here's an example that demonstrates all of these possibilities:
<o:forEach items="#{MyBean.tasks}" begin="#{MyBean.lastTaskIndex}" end="0" step="-1" var="task" varStatus="status"> <h:outputText value="#{status.count}. (#{status.index}) -- #{task.name}"/> <br/> </o:forEach>
The begin and end attributes specify the zero-based indexes that specify the sub-range of the displayed items. These numbers are inclusive which means that both boundaries of the range are included into iteration. The step attribute specifies the index increase step between the successive iteration rounds. It's possible to specify the begin value greater than the end value for the reverse iteration order, but in this case you'll also need to specify a negative step value, as shown in the example above.
Note that the count property of the iteration status object always returns values 1, 2, 3, etc... regardless of the range settings, and the index property returns the actual zero-based collection index for the current iteration step, so in case of three-item collection, it will take the values of 2, 1, 0 in the example above.
It is possible not to specify the collection of items, and just specify the begin, end, and optionally step attributes for the <o:forEach> tag, which will perform the iteration similar to how it is described in the previous section but without using the collection items. The count and index iteration parameters will still have the same meaning as described in the previous section, but the value of the var variable (and the current property in iteration status) will return null. Here's a simple example of number-based, which creates five <div> tags with a 1-based number within each of them:
<o:forEach begin="1" end="5" varStatus="status"> <div>#{status.index}</div> </o:forEach>
- It's not possible to use input components in nested ForEach components.