Edit on GitHub << back to Tag Reference

# iterator

Please make sure you have read the Tag Syntax document and understand how tag attribute syntax works.

> NOTE: The `id` attribute is deprecated in Struts 2.1.x, and has been replaced by the `var` attribute. The `begin`, `end` and `step` attributes are only available from 2.1.7+

## Description

Iterator will iterate over a value. An iterable value can be any of: `java.util.Collection`, `java.util.Iterator`, `java.util.Enumeration`, `java.util.Map`, or an array.

Iterate over a iterable value

## Attributes

#### Dynamic Attributes Allowed: false
#### Name | #### Required | #### Default | #### Evaluated | #### Type | #### Description
--- | --- | --- | --- | --- | ---
begin | false | 0 | false | Integer | if specified the iteration will start on that index
end | false | Size of the 'values' List or array, or 0 if 'step' is negative | false | Integer | if specified the iteration will end on that index(inclusive)
performClearTagStateForTagPoolingServers | false | false | false | Boolean | Whether to clear all tag state during doEndTag() processing (if applicable)
status | false | false | false | Boolean | If specified, an instanceof IteratorStatus will be pushed into stack upon each iteration
step | false | 1 | false | Integer | if specified the iteration index will be increased by this value on each iteration. It can be a negative value, in which case 'begin' must be greater than 'end'
value | false |  | false | String | the iteratable source to iterate over, else an the object itself will be put into a newly created List
var | false |  | false | String | Name used to reference the value pushed into the Value Stack (scope: action).

## Conversion

Values generated by the tag are subject of internal conversion mechanism. It means when generating ordinary numbers and then using them with `<s:property/>`, the Integers will be converted to Strings using the current locale. This can impact how the numbers are presented. Since Struts 6.4.0 to avoid conversion you can use the `status` object and its `countStr` and `indexStr` which are a String representation of the numbers. The following example demonstrates the case when using `fa_IR` locale:

    <s:iterator begin="1" end="3" status="status">
        <s:property/>
        <s:textfield id="text_%{#status.countStr}" name="test[%{#status.indexStr}]"/>
    </s:iterator>

    ۰
    <input type="text" name="test[0]" value="" id="text_1">
    ۱
    <input type="text" name="test[1]" value="" id="text_2">
    ۲
    <input type="text" name="test[2]" value="" id="text_3">

## Examples

The following example retrieves the value of the getDays() method of the current object on the value stack and uses it to iterate over. The `<s:property/>` tag prints out the current value of the iterator.

    <s:iterator value="days">
      <p>day is: <s:property/></p>
    </s:iterator>

The following example uses a Bean tag and places it into the `ActionContext`. The iterator tag will retrieve that object from the `ActionContext` and then calls its `getDays()` method as above. The status attribute is also used to create an `IteratorStatus` object, which in this example, its `odd()` method is used to alternate row colours:

    <s:bean name="org.apache.struts2.example.IteratorExample" var="it">
      <s:param name="day" value="'foo'"/>
      <s:param name="day" value="'bar'"/>
    </s:bean>

    <table border="0" cellspacing="0" cellpadding="1">
    <tr>
      <th>Days of the week</th>
    </tr>

    <s:iterator value="#it.days" status="rowstatus">
      <tr>
        <s:if test="#rowstatus.odd == true">
          <td style="background: grey"><s:property/></td>
        </s:if>
        <s:else>
          <td><s:property/></td>
        </s:else>
      </tr>
    </s:iterator>
    </table>

The next example will further demonstrate the use of the status attribute, using a DAO obtained from the action class through OGNL, iterating over groups and their users (in a security context). The last() method indicates if the current object is the last available in the iteration, and if not, we need to separate the users using a comma:

    <s:iterator value="groupDao.groups" status="groupStatus">
        <tr class="<s:if test="#groupStatus.odd == true ">odd</s:if><s:else>even</s:else>">
            <td><s:property value="name" /></td>
            <td><s:property value="description" /></td>
            <td>
                <s:iterator value="users" status="userStatus">
                    <s:property value="fullName" /><s:if test="!#userStatus.last">,</s:if>
                </s:iterator>
            </td>
        </tr>
    </s:iterator>

The next example iterates over a an action collection and passes every iterator value to another action. The trick here lies in the use of the `[0]` operator. It takes the current iterator value and passes it on to the edit action. Using the `[0]` operator has the same effect as using `<s:property />`. (The latter, however, does not work from inside the `param` tag).

    <s:action name="entries" var="entries"/>
    <s:iterator value="#entries.entries" >
        <s:property value="name" />
        <s:property />
        <s:push value="...">
            <s:action name="edit" var="edit" >
                <s:param name="entry" value="[0]" />
            </s:action>
        </push>
    </s:iterator>

A loop that iterates 5 times

    <s:iterator var="counter" begin="1" end="5" >
       <!-- current iteration value (1, ... 5) -->
       <s:property value="top" />
    </s:iterator>

Another way to create a simple loop, similar to JSTL’s `<c:forEach begin="..." end="..." ...>` is to use some OGNL magic, which provides some under-the-covers magic to make 0-n loops trivial. This example also loops five times.

    <s:iterator status="stat" value="(5).{ #this }" >
       <s:property value="#stat.count" /> <!-- Note that "count" is 1-based, "index" is 0-based. -->
    </s:iterator>

A loop that iterates over a partial list

    <s:iterator value="{1,2,3,4,5}" begin="2" end="4" >
       <!-- current iteration value (2,3,4) -->
       <s:property value="top" />
    </s:iterator>

Another example when we can access a variable out of the current loop context and where name clashes with the current

    <s:select name="location" size="1" list="locations" listKey="key"
      listValue="value" emptyOption="false" />

    <s:iterator var="item" value="items" status="rowstatus">
        <s:url var="myUrl" action="itemDelete">
            <s:param name="id" value="#item.id" />
            <%-- Outer loop variable name [1]. as clash with item.location --%>
            <s:param name="location" value="[1].location" />
        </s:url>
    </s:iterator>