Recipe3.5.Using Indexed Properties in a JSTL Loop


Recipe 3.5. Using Indexed Properties in a JSTL Loop

Problem

You want to use indexed bean properties with the Struts html tags in a JSTL c:forEach loop instead of Struts logic:iterate loop.

Solution

To create fields for a simple indexed property, use the bean:define tag to expose the loop counter as a scripting variable that can be used in a runtime expression:

<c:forEach var="theItem" items="${MyForm.myItems}" varStatus="loopStatus">   <bean:define >     <c:out value="${loopStatus.index}"/>   </bean:define>   <br/><html:text property='<%="myItem["+itemIndex+"]"%>'/> </c:forEach>

If the indexed property is a nested bean and you are using the indexed="true" property, then replace the Struts logic:iterate tag with the JSTL c:forEach:

<c:forEach var="theNestedItem" items="${MyForm.myNestedItems}">   <br/><html:text name="theNestedItem"                property="nestedProperty"               indexed="true"/> </c:forEach>

Discussion

The c:forEach tag provided by JSTL provides additional functionality and can be easier to use than the logic:iterate tag. The items to loop through can be specified using EL. The JSTL tag permits greater control for looping over a subset of the collection, and details on the loop status are easily obtained. However, as is common to all JSTL tags, no scripting variables are created. As was shown in other recipes in this chapter, runtime expressions may have to be used when dealing with indexed properties. This is particularly true if you are not using the struts-el tag libraries.

The bean:define tag can create a scripting variable from a JSTL-created scoped variables. This bean:define tag creates a new scoped variable and a corresponding scripting variable based on the value taken from the value attribute or the body of the tag. This latter facility provides a useful bridge between JSTL and the Struts tags. In the Solution, the bean:define tag is used to create a variable containing the index to use for accessing the indexed property. You can apply this technique to the form for selecting the favorite colors from Recipe 3.4:

What are your three favorite colors: <c:forEach var="theColor" items="${FavoritesForm.color}"      varStatus="loopStatus">     <bean:define >         <c:out value="${loopStatus.index}"/>     </bean:define>     <br/><html:text property='<%="color["+ctr+"]"%>'/> </c:forEach>

As shown in Recipe 3.4, you can use the Struts-El tags to eliminate the scriptlet altogether:

What are your three favorite colors: <c:forEach var="theColor" items="${FavoritesForm.color}"  varStatus="loopStatus">   <br/><html-el:text property='color[${ctr}]'/> </c:forEach>

If you need to create an HTML input field for the nested property of an object, which is an indexed property, then specify the indexed="true" attribute on the Struts html tags. The usage of the indexed attribute is identical when used in a JSTL c:forEach loop as when using the logic:iterate tag. Here is an example of how this would be done for the Favorite Links portion of the form from Recipe 3-4:

What are your favorite links? <table>     <tr>         <th>Name</th>         <th>URL</th>     </tr>     <c:forEach var="webLink" items="${FavoritesForm.webLinks}">         <tr>             <td>                 <html:text name="webLink"                         property="name" indexed="true"/>             </td>             <td>                 <html:text name="webLink"                         property="url" indexed="true"/>             </td>         </tr>     </c:forEach> </table>

The rendered index values are generated correctly even when using the begin, end, and step attributes to control the loop. The following use of the c:forEach tag demonstrates how to generate input fields for the first and third elements of a collection:

<c:forEach var="webLink" items="${FavoritesForm.webLinks}"          begin="1" end="3" step="2">     <tr>         <td>             <html:text name="webLink" property="name" indexed="true"/>         </td>         <td>             <html:text name="webLink" property="url" indexed="true"/>         </td>     </tr> </c:forEach>

This results in the following generated HTML:

<tr>     <td><input type="text" name="webLink[1].name" value=""></td>     <td><input type="text" name="webLink[1].url" value=""></td> </tr>           <tr>     <td><input type="text" name="webLink[3].name" value=""></td>     <td><input type="text" name="webLink[3].url" value=""></td> </tr>

For rendering dynamic data in a loop for display, JSTL works well and should be easier to use than the corresponding Struts tags. As you have seen, JSTL has better support for accessing indexed properties than the Struts tags. For example, the following shows how the favorite colors could be displayed:

<c:forEach var="color" items="${favs.color}">     <li><c:out value="${color}"/></li> </c:forEach>

See Also

Recipe 3.4 demonstrates similar usages of indexed properties. You should consult the JSTL documentation if needed. The specification provides additional details on the tags mentioned here. The specification can be found at http://java.sun.com/jsp/jstl.



    Jakarta Struts Cookbook
    Jakarta Struts Cookbook
    ISBN: 059600771X
    EAN: 2147483647
    Year: 2005
    Pages: 200

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net