org.apache.tapestry.corelib.components.Grid

A grid presents tabular data. It is a composite component, created in terms of several sub-components. The sub-components are statically wired to the Grid, as it provides access to the data and other models that they need. A Grid may operate inside a org.apache.tapestry.corelib.components.Form. By overriding the cell renderers of properties, the default output-only behavior can be changed to produce a complex form with individual control for editing properties of each row. This is currently workable but less than ideal -- if the order of rows provided by the org.apache.tapestry.grid.GridDataSource changes between render and form submission, then there's the possibility that data will be applied to the wrong server-side objects.

[JavaDoc]

Component Parameters

NameTypeFlagsDefaultDefault PrefixDescription
addStringliteralA comma-seperated list of property names to be added to the org.apache.tapestry.beaneditor.BeanModel. Cells for added columns will be blank unless a cell override is provided.
classStringt-data-gridliteralCSS class for the table element. In addition, informal parameters to the Grid are rendered in the table element.
emptyorg.apache.tapestry.Blockblock:emptypropA Block to render instead of the table (and pager, etc.) when the source is empty. The default is simply the text "There is no data to display". This parameter is used to customize that message, possibly including components to allow the user to create new objects.
excludeStringliteralA comma-separated list of property names to be removed from the org.apache.tapestry.beaneditor.BeanModel. The names are case-insensitive.
includeStringliteralA comma-separated list of property names to be retained from the org.apache.tapestry.beaneditor.BeanModel. Only these properties will be retained, and the properties will also be reordered. The names are case-insensitive.
leanbooleanpropIf true, then the CSS class on each TD and TH cell will be omitted, which can reduce the amount of output from the component overall by a considerable amount. Leave this as false, the default, when you are leveraging the CSS to customize the look and feel of particular columns.
modelorg.apache.tapestry.beaneditor.BeanModelpropThe model used to identify the properties to be presented and the order of presentation. The model may be omitted, in which case a default model is generated from the first object in the data source (this implies that the objects provided by the source are uniform). The model may be explicitly specified to override the default behavior, say to reorder or rename columns or add additional columns.
pagerPositionorg.apache.tapestry.corelib.data.GridPagerPositiontopliteralDefines where the pager (used to navigate within the "pages" of results) should be displayed: "top", "bottom", "both" or "none".
reorderStringliteralA comma-separated list of property names indicating the order in which the properties should be presented. The names are case insensitive. Any properties not indicated in the list will be appended to the end of the display order.
rowObjectpropUsed to store the current object being rendered (for the current row). This is used when parameter blocks are provided to override the default cell renderer for a particular column ... the components within the block can use the property bound to the row parameter to know what they should render.
rowClassStringNOT CachedpropThe CSS class for the tr element for each data row. This can be used to highlight particular rows, or cycle between CSS values (for the "zebra effect"). If null or not bound, then no particular CSS class value is used.
rowsPerPageint25propThe number of rows of data displayed on each page. If there are more rows than will fit, the Grid will divide up the rows into "pages" and (normally) provide a pager to allow the user to navigate within the overall result set.
sortModelorg.apache.tapestry.grid.GridSortModelpropThe model used to handle sorting of the Grid. This is generally not specified, and the built-in model supports only single column sorting. The sort constraints (the column that is sorted, and ascending vs. descending) is stored as persistent fields of the Grid component.
sourceorg.apache.tapestry.grid.GridDataSourceRequiredpropThe source of data for the Grid to display. This will usually be a List or array but can also be an explicit org.apache.tapestry.grid.GridDataSource. For Lists and object arrays, a GridDataSource is created automatically as a wrapper around the underlying List.
volatilebooleanpropIf true and the Loop is enclosed by a Form, then the normal state persisting logic is turned off. Defaults to false, enabling state persisting within Forms. If a Grid is present for some reason within a Form, but does not contain any form control components (such as org.apache.tapestry.corelib.components.TextField), then binding volatile to false will reduce the amount of client-side state that must be persisted.

Related Components

Simple Example

The Grid component is closely related to the BeanEditor component; they are both based on the same underlying concept and share quite a bit of code. In this example, we'll display a list of users. We'll also show some basic customization, to convert a column from just text, to a clickable link.

This example shows much of the default behavior, using a collection of randomly generated users. The column order is determined by the order of the getter methods in the User class. The columns are sortable, and because there are more results than will fit on a single page, page navigation is included (the navigation disappears for small result sets).

User.java

public class User
{
    private long _id;

    private String _firstName;

    private String _lastName;

    private int _age;

    public long getId() { return _id; }

    @NonVisual
    public void setId(long id) { _id = id; }

    public String getFirstName() { return _firstName; }

    public void setFirstName(String firstName) { _firstName = firstName; }

    public String getLastName() { return _lastName; }

    public void setLastName(String lastName) { _lastName = lastName; }

    public int getAge() { return _age; }

    public void setAge(int age) { _age = age; }
}

The @NonVisual annotation prevents the id property from being displayed.

UserList.tml

We want to make the user's last name a clickable link to a detail page for the user.

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
    <body>
        <h1>List Users</h1>

        <t:grid source="users" row="user">
            <t:parameter name="lastnamecell">
                <t:pagelink page="user/view" context="user.id">${user.lastname}</t:pagelink>
            </t:parameter>
        </t:grid>
    </body>
</html>

The parameter name propertycell is used to override the rendering of cells for one property. As usual, case is ignored. Here we use a PageLink component to link to a ViewUser page, passing the id of the user as activation context for the target page.

The Grid component takes care of the <td> element, and the provided block parameter provides the content inside the <td>.

For the block to know what is being rendered, we bind the row parameter of the Grid to the user property of the page. The Grid will keep updating this property just before it renders each row (using its own internal renderers, or the ones provided as parameters).

The header for a column may be overridden in the same way, using a parameter name of propertyheader . The parameter block will provide the content inside the <th> element. The provided block is responsible for providing any links or icons related to sorting.

UserList.java

public class UserList
{
    @Inject
    private UserDAO _userDAO;

    private User _user;

    public List<User> getUsers() { return _userDAO.findAll(); }

    public void setUser(User user) { _user = user; }

    public User getUser() { return _user; }
}

The UserList class exists to provide access to the UserDAO service, and to act as a holder for the user property, needed when the Grid is rendering. We need it here because we've overridden the rendering of the lastName property.

Adding Columns Example

Commonly, you may want to add a column to the Grid to support a computed property, or as a placeholder for an action. We'll do the latter, adding a column for deleting a user.

UserList.tml

We want to make the user's last name a clickable link to delete the user for that row.

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
    <body>
        <h1>List Users</h1>

        <t:grid source="users" row="user" model="model">
            <t:parameter name="lastnamecell">
                <t:pagelink page="user/view" context="user.id">${user.lastname}</t:pagelink>
            </t:parameter>
            <t:parameter name="deletecell">
                <t:actionlink t:id="delete" context="user.id">Delete</t:actionlink>
            </t:parameter>
        </t:grid>
    </body>
</html>

We now explicitly provide a model parameter. In addition, a block for the "delete" property has been added that includes an ActionLink used to delete the user for the current row. This property is a virtual property because it doesn't correspond to a property of the data object, User.

UserList.java

public class UserList
{
    @Inject
    private UserDAO _userDAO;

    @Inject
    private BeanModelSource _beanModelSource;

    @Inject
    private ComponentResources _resources;

    private final BeanModel _model;

    {
        _model = _beanModelSource.create(User.class, true, _resources);

        _model.add("delete", null);
    }

    private User _user;

    public List<User> getUsers() { return _userDAO.findAll(); }

    public void setUser(User user) { _user = user; }

    public User getUser() { return _user; }

    public BeanModel getModel() { return _model; }

    void onActionFromDelete(long userId)
    {
        _userDAO.remove(userId);
    }  
}

Here we create the model using the BeanModelSource service. We then customize it, adding a new property, "delete". The null indicates that this is a virtual property, with no real data behind it.

UserList.properties

delete-label=Delete user?

The normal column title for the "delete" property would be "Delete". Using the page's message catalog we can override that.

Notes

Tapestry does a lot of work to help you with the source parameter. The parameter type is GridDataSource, but Tapestry has built-in coercions from Object[] and List. In more complicated cases, such as very large queries against a database, you will want to provide your own implementation of GridDataSource, to minimimze the sizes of queries and result sets.

CSS

The Grid component is designed to be customized via CSS. As it renders <th>, <tr> and <td> elements, it generates CSS class attributes for each element. You can then add customized CSS rules, even overriding the Tapestry defaults, to present the Grid as desired. This is often used to set the width of a column to a fixed value.

propertyId
Added to <th> elements to allow customization of a particular column's header, and added to <td> elements to allow customization of a particular column's data cells.
t-first
Added to the first <th> and the first <tr> of the <tbody> (the data portion of the table).
t-last
Added to the last <th> and the last <tr>.
t-sort-column-ascending
Added to the <th> and all corresponding <td> elements for the column that is the current sort column (if any, for ascending sort).
t-sort-column-descending
As with t-soft-column-ascending, but for a descending sort.

The added CSS classes can get quite verbose; the Grid's lean parameter allows the propertyId CSS class attribute value to be omitted. Even in lean mode, the other CSS class attribute values are rendered.


Back to index