<html:select> inside <logic:iterate>

TPT Gin picture TPT Gin · Nov 26, 2011 · Viewed 11.5k times · Source

I have an itemList and for each item, a dropdown list of ratings is displayed. After user rates each item in itemList, i want to store those rates in an array. How can I do it? selectedRate below is of Integer type, and the code failed to solve the problem.

<logic:iterate id="item" name="itemList">
  <tr>
    <td>
      <html:select name="aForm" property="selectedRate">
        <html:optionsCollection name="allRates" label="description" value="value" />
      </html:select>
    </td>
  </tr>
</logic:iterate>

Answer

Dave Newton picture Dave Newton · Nov 26, 2011

Each select option needs to be associated with a specific item.

The easiest way is to use a collection of Items, and give each Item a rating property. I used an Integer for this example.

The <html:select> uses array notation, and directly sets each item's rating. (I'm using a list of rates from the form itself, and a simpler layout; ignore those differences.)

<logic:iterate id="item" name="ratesForm" property="itemList" indexId="i">
  ${item.name}&nbsp;
  <html:select property="itemList[${i}].rating">
    <html:optionsCollection name="ratesForm" property="rates" label="description" value="value" />
  </html:select>
  <br/>
</logic:iterate>

The action accesses the item ratings as we'd expect:

RatesForm ratesForm = (RatesForm) form;
List<Item> items = ratesForm.getItemList();
for (Item item : items) {
    System.out.println(item.rating);
}

If the items do not have an associated rating, you'll need to use a map of item id keys and rating values. This is more convoluted; I recommend a collection.

First, the map will be Map<String, Object> because of the way indexed properties work. In addition to a normal getter for the map itself, provide indexed methods:

private Map<String, Object> itemRatings;

public Map<String, Object> getItemRatings() {
    return itemRatings;
}

public Object getItemRating(String key) {
    return itemRatings.get(key);
}

public void setItemRating(String key, Object val) {
    itemRatings.put(key, val);
}

The JSP will be similar, but use "()" instead of "[]" to use the indexed form methods.

<logic:iterate id="item" name="ratesForm" property="itemList">
    ${item.name}&nbsp;
      <html:select property="itemRating(${item.id})">
        <html:optionsCollection name="ratesForm" property="rates" label="description" value="value" />
      </html:select>
    <br/>
</logic:iterate>

When the form is submitted, the itemRatings map will contain string keys representing each item's ID. Both the key and the value will be Strings, and you'll need to make any conversions to numeric values manually.