| <document> |
| <body> |
| <section name="Related Components"> |
| <ul> |
| <li> |
| <a href="BeanEditForm">BeanEditForm</a> |
| </li> |
| <li> |
| <a href="BeanDisplay">BeanDisplay</a> |
| </li> |
| </ul> |
| </section> |
| |
| <section name="Simple Example"> |
| |
| <p> |
| 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. |
| </p> |
| |
| <p>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. |
| </p> |
| |
| <p> |
| <img src="grid_ref1.png"/> |
| </p> |
| |
| <p>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). |
| </p> |
| |
| <subsection name="User.java"> |
| <source><![CDATA[ |
| 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; } |
| }]]></source> |
| |
| <p>The @NonVisual annotation prevents the id property from being displayed.</p> |
| |
| </subsection> |
| |
| <subsection name="UserList.tml"> |
| |
| <p> |
| We want to make the user's last name a clickable link to a detail page for the user. |
| </p> |
| |
| |
| <source><![CDATA[ |
| <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> |
| ]]></source> |
| |
| |
| <p> |
| The parameter name |
| <code><em>property</em>cell |
| </code> |
| 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. |
| </p> |
| |
| <p> |
| The Grid component takes care of the <td> element, and the provided block parameter |
| provides the content |
| <em>inside</em> |
| the <td>. |
| </p> |
| |
| <p> |
| 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). |
| </p> |
| |
| <p> |
| The header for a column may be overridden in the same way, using a parameter name |
| of |
| <code><em>property</em>header |
| </code> |
| . 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. |
| </p> |
| |
| </subsection> |
| |
| <subsection name="UserList.java"> |
| <source><![CDATA[ |
| public class UserList |
| { |
| @Inject |
| private UserDAO _userDAO; |
| |
| @Property |
| private User _user; |
| |
| public List<User> getUsers() { return _userDAO.findAll(); } |
| }]]></source> |
| |
| </subsection> |
| |
| <p> |
| 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. |
| </p> |
| |
| </section> |
| |
| <section name="Adding Columns Example"> |
| |
| <p> |
| 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. |
| </p> |
| |
| |
| <p> |
| <img src="grid_ref2.png"/> |
| </p> |
| |
| <subsection name="UserList.tml"> |
| |
| |
| <source><![CDATA[ |
| <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"> |
| <body> |
| <h1>List Users</h1> |
| |
| <t:grid source="users" row="user" add="delete"> |
| <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> |
| ]]></source> |
| |
| <p> |
| We now explicitly provide a column for the "delete" property, which doesn't exist. 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 |
| <em>virtual</em> |
| property because it doesn't correspond to a property |
| of the data object, User. |
| </p> |
| |
| </subsection> |
| |
| <subsection name="UserList.java"> |
| <source><![CDATA[ |
| public class UserList |
| { |
| @Inject |
| private UserDAO _userDAO; |
| |
| @Property |
| private User _user; |
| |
| public List<User> getUsers() { return _userDAO.findAll(); } |
| |
| void onActionFromDelete(long userId) |
| { |
| _userDAO.remove(userId); |
| } |
| }]]></source> |
| |
| |
| <p> |
| The only addition here is an event handler method for when the delete link is clicked. |
| </p> |
| |
| |
| </subsection> |
| |
| <subsection name="UserList.properties"> |
| <source><![CDATA[ |
| delete-label=Delete user?]]></source> |
| |
| <p> |
| The normal column title for the "delete" property would be "Delete". Using the |
| page's message catalog we can override that. |
| </p> |
| </subsection> |
| |
| |
| </section> |
| |
| |
| <section name="Notes"> |
| |
| <p> |
| 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. |
| </p> |
| |
| |
| <subsection name="CSS"> |
| |
| <p>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. |
| </p> |
| |
| <dl> |
| <dt> |
| <em>propertyId</em> |
| </dt> |
| <dd>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. |
| </dd> |
| |
| <dt>t-first</dt> |
| <dd>Added to the first <th> and the first <tr> of the <tbody> (the data portion of |
| the table). |
| </dd> |
| |
| <dt>t-last</dt> |
| <dd>Added to the last <th> and the last <tr>.</dd> |
| |
| <dt>t-sort-column-ascending</dt> |
| <dd>Added to the <th> and all corresponding <td> elements for the column that is the |
| current sort column (if any, |
| for ascending sort). |
| </dd> |
| |
| <dt>t-sort-column-descending</dt> |
| <dd>As with t-soft-column-ascending, but for a descending sort.</dd> |
| |
| </dl> |
| |
| <p> |
| 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. |
| </p> |
| |
| </subsection> |
| |
| </section> |
| |
| |
| </body> |
| </document> |