Spring 3 allows for wonderfully simply forms and automatic binding of form values back to the command object. However if your command object has further nested objects that you want to make editable from the form as well things get a little tricky. In that case you can’t just use a standard JSTL forEach loop as this will not allow you to build the path to the nested object correctly. The trick is to use the varStatus attribute to keep track of the index.

Sets and Lists

Assuming that your command object is called target the following will do just fine:

<ul>
  <c:forEach items="${target.nestedObjects}" varStatus="index">
    <li>
      <form:input path="nestedObjects[${index.count - 1}].property" />
      <form:errors path="nestedObjects[${index.count - 1}].property" cssClass="errors" />
    </li>
  </c:forEach>
</ul>

Keep in mind that the varStatus counter is one-based while most collections’ indices are zero-based; hence the “itemIndex.count – 1” expression.

Another way is to use the <spring:bind> tag. This will allow you to use standard HTML-Tags at the expense of some Spring form tricks such as checkboxes that are always submitted.

<ul>
  <c:forEach items="${target.nestedObjects}" varStatus="index">
    <li>
      <spring:bind path="nestedObjects[${index.count - 1}].property" />
      <input type="text" name="${status.expression}" value="${status.value}" />
      <p class="errors">${status.errorMessages}</p>
    </li>
  </c:forEach>
</ul>

Of course you can also mix and match both approaches as you see fit.

Maps

To iterate over a map the approach is slightly different:

<ul>
  <c:forEach items="${target.nestedMap}" varStatus="index">
    <li>
      <form:input path="nestedObjects[${index.current.key}].property" />
      <form:errors path="nestedObjects[${index.current.key}].property" cssClass="errors" />
    </li>
  </c:forEach>
</ul>

As you can see the varStatus variable will be set to each respective map entry as they are iterated. Therefore “index.current.value” is also available if needed.