LinkSubmit Component Index Option

ListEdit
org.apache.tapestry.form.ListEdit
Non Visual Component
 
Description
A component used to iterate through a list of items within a Form. The ListEdit is similar to a Foreach but uses hidden input fields within the <form> to store the items in the list.

An instance of DataSqueezer is used to convert arbitrary objects into Strings and then back into objects. However, for best efficiency, the list should be simple Strings or numeric types, typically a primary key or other identifier from which the rest of an object may be retrieved or constructed. Serializable objects will work, but the resultant string can be very, very large.

See Also
Foreach, Form, Hidden
Parameters
Name Type Direction Required Default Description
source List,
Iterator or
Object[]
in yes   The list of values to be editted within the form. This list is only read when the component renders; it records hidden input fields in the form to guide things when the form is submitted.

The source can contain objects of any type, though they should be serializable. Ideally, the objects should be String or wrapper types such as Integer. In other words, the source should be a list of primary keys of the objects being editted.

value Object out yes   The value for each iteration through the list (during render or rewind).
index int out no   The index (starting at zero) for each iteration through the list.
listener IActionListener in no   A listener that is informed after the value parameter is updated. This allows the data set operated on by the rest of the Form components to be synchronized to the value stored in the hidden field.

A typical use is to encode the primary key of an entity as a Hidden; when the form is submitted, the Hidden's listener re-reads the corresponding entity from the database.

element String in no   If specified, then a tag for the specified element is placed around the content on each iteration. This emulates the Any component. Most often the element specified is "tr" when the ListEdit is part of a table. Any informal parameters are applied to the element.

Body: rendered
Informal parameters: allowed
Reserved parameters: none

Examples

This ListEdit control is typically used in conjuction with the ListEditMap class. To understand how the ListEdit control works you need to understand the how forms are rewound. But before we get into that lets see an example of the ListEdit control in action. This example is from the vlib sample application and allows the user to edit a list of publishers.

HTML:

The following code sets up list of TextField components for editing the publisher names. A checkbox is used to mark publishers to be deleted from the database. It's pretty similar to a Foreach component at this stage.

    <tr jwcid="listEdit">
<td class="control"><input jwcid="inputName@TextField" value="ognl:publisher.name" size="40" maxlength="40"/>
</td>
<td class="checkbox"><input type="checkbox" jwcid="delete@Checkbox" selected="ognl:listEditMap.deleted"/>
</td>
</tr>

Page file:

The page file sets up some page properties for the ListEditMap and current publisher. The listEdit component is where it gets interesting. The source binding is the set of all keys in the list edit map. Basically the list of all the publishers identifers. The value is the current key. It would actually be possible to use the publisher object as the value however because each value object is serialized this could get pretty inefficient. Instead what happens is a listener is setup. This listener sets up the actual publisher object from the key when the form is rewound.

  <property-specification name="listEditMap" type="org.apache.tapestry.form.ListEditMap"/>
<property-specification name="publisher" type="org.apache.tapestry.vlib.ejb.Publisher"/>

<component id="listEdit" type="ListEdit">
<binding name="source" expression="listEditMap.keys"/>
<binding name="value" expression="listEditMap.key"/>
<static-binding name="element" value="tr"/>
<binding name="listener" expression="listeners.synchronizePublisher"/>
</component>

Code:

In the code part of this example consists of the abstract properties we set up earlier and three important methods. The synchronizePublisher() method is used to set the Publisher object from the keys we are storing in the listEditMap property. The secret to understanding how it works lies in understanding the rewind cycle. During rewind the listener method is called multiple times - once for each row. The rewind process calls listEditMap.setKey(). This effects the current value returned by listEditMap.getValue(). Once the current publisher is setup calls from the TextField component control the setting of the necessary publisher object properties.

The next two methods are easier to understand. The readPublishers() call populates the listEditMap property with the set of all publishers to be edited. It is called from pageBeginRender(). The processForm() method handles the form submit. All updated publishers are in map.getValues() and deleted publishers are returned by map.getDeletedKeys().

    public abstract ListEditMap getListEditMap();
    public abstract void setListEditMap(ListEditMap listEditMap);
    public abstract Publisher getPublisher();
    public abstract void setPublisher(Publisher publisher);

    public void synchronizePublisher(IRequestCycle cycle)
    {
        ListEditMap map = getListEditMap();

        Publisher publisher = (Publisher) map.getValue();

        if (publisher == null)
        {
            setError(getMessage("out-of-date"));
            throw new PageRedirectException(this);
        }

        setPublisher(publisher);
    }
    private void readPublishers()
{
... ListEditMap map = new ListEditMap(); int count = Tapestry.size(publishers); for (i = 0; i < count; i++) map.add(publishers[i].getId(), publishers[i]); setListEditMap(map); }
public void processForm(IRequestCycle cycle) { ... ListEditMap map = getListEditMap(); List updateList = map.getValues(); List deletedIds = map.getDeletedKeys(); // update and delete publishers }
 

LinkSubmit Component Index Option