views:

57

answers:

1

In Tapestry 4 I am trying it iterate over a list of lists (technically a list of objects who have a list of strings as a data field). I am currently doing this by using 'nested' for components.

(This is pseudo code)

<span jwcid="Form">
<span jwcid="@For" source="ognl:Javaclass.TopLevelList" value="ognl:SecondLevelList" index="ognl:index">
<span jwcid="@For" source="ognl:SecondLevelList.List" value="ognl:ListItem" index="ListItemIndex">
<span jwcid="@TextField" value="ognl:ListItem"/>
<span jwcid="@Submit" listener="ognl:listeners.onSubmit"/>
</span></span></span>

The onSubmit listener then accesses the index and ListItem index page properties, as well as the ListItem page property in order to correctly update the list in Javaclass.TopLevelList.

This works fine, but it looks terrible, and is cumbersome to the end user. I would prefer to somehow simulate this functionality using only one submit button at the bottom of the page.

I have looked into somehow using the overlying form component to obtain a list of the 'form control components' within it, and then (with great care) parsing through tapestry's naming conventions to recover the functionality of the indexes.

If anyone knows how to do this, or could explain the form component (how/when it submits, etc.) it would be greatly appreciated.

A: 

Tapestry 4 stores the lists in hidden fields and then runs through the same loop again when the form is submitted (that's the rewinding phase), updating values and invoking listeners along the way. Rewinding makes sure all page properties have correct values when the listener is invoked.

If I understand you correctly I believe you can remove the @Submit and instead bind the @TextField to a synthetic property like so:

<span jwcid="@TextField" value="ognl:ListItemBeingEdited"/>

And then do work in the setter, which will be invoked once for each textfield:

public void setListItemBeingEdited(... listItemValue)
{
  // Form was submitted and is now rewinding
  // We're being passed a value from the textfield 
  // and all other page properties are set up correctly, so...
  letsDoStuff(index, listItemIndex, listItemValue);
}

public void ... getListItemBeingEdited()
{
  return getListItem();
}
Martin