Package org.apache.tapestry5.corelib.components

# Class Grid

java.lang.Object
org.apache.tapestry5.corelib.components.Grid

All Implemented Interfaces:
  `ClientElement`, `GridModel`

@SupportsInformalParameters public class Grid extends Object implements GridModel, ClientElement
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 `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. There is a big caveat here: if the order of rows provided by the `GridDataSource` changes between render and form submission, then there's the possibility that data will be applied to the wrong server-side objects. For this reason, when using Grid and Form together, you should generally provide the Grid with a `ValueEncoder` (via the encoder parameter), or use an entity type for the "row" parameter for which Tapestry can provide a ValueEncoder automatically. This will allow Tapestry to use a unique ID for each row that doesn't change when rows are reordered.

See Also:
  - `BeanModel`
  - `BeanModelSource`
  - `GridDataSource`
  - `BeanEditForm`
  - `BeanDisplay`
  - `Loop`

Component Parameters
Name | Type | Flags | Default | Default Prefix
--- | --- | --- | --- | ---
add | String |  |  | literal
A comma-separated list of property names to be added to the org.apache.tapestry5.beanmodel.BeanModel. Cells for added columns will be blank unless a cell override is provided. This parameter is only used when a default model is created automatically.
class | String |  | symbol:tapestry.components.grid_table_css_class | literal
CSS class for the table element. In addition, informal parameters to the Grid are rendered in the table element.
columnIndex | int |  |  | prop
Optional output parameter used to identify the index of the column being rendered.
empty | org.apache.tapestry5.Block |  | block:empty | literal
A 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.
encoder | org.apache.tapestry5.ValueEncoder |  |  | prop
A ValueEncoder used to convert server-side objects (provided by the "row" parameter) into unique client-side strings (typically IDs) and back. In general, when using Grid and Form together, you should either provide the encoder parameter or use a "row" type for which Tapestry is configured to provide a ValueEncoder automatically. Otherwise Tapestry must fall back to using the plain index of each row, rather than the ValueEncoder-provided unique ID, for recording state into the form.
exclude | String |  |  | literal
A comma-separated list of property names to be removed from the org.apache.tapestry5.beanmodel.BeanModel . The names are case-insensitive. This parameter is only used when a default model is created automatically.
inPlace | boolean |  |  | prop
If true, then the Grid will be wrapped in an element that acts like a org.apache.tapestry5.corelib.components.Zone; all the paging and sorting links will refresh the zone, repainting the entire grid within it, but leaving the rest of the page (outside the zone) unchanged.
include | String |  |  | literal
A comma-separated list of property names to be retained from the org.apache.tapestry5.beanmodel.BeanModel. Only these properties will be retained, and the properties will also be reordered. The names are case-insensitive. This parameter is only used when a default model is created automatically.
lean | boolean |  |  | prop
If true, then the CSS class on each TD 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.
model | org.apache.tapestry5.beanmodel.BeanModel |  |  | prop
The 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. The add, include, exclude and reorder parameters are only applied to a default model, not an explicitly provided one.
overrides | org.apache.tapestry5.PropertyOverrides | Not Null | this | prop
Defines where block and label overrides are obtained from. By default, the Grid component provides block overrides (from its block parameters).
pagerPosition | org.apache.tapestry5.corelib.data.GridPagerPosition |  | symbol:tapestry.components.grid_pager_position | literal
Defines where the pager (used to navigate within the "pages" of results) should be displayed: "top", "bottom", "both" or "none".
paginationModel | org.apache.tapestry5.grid.GridPaginationModel | Since 5.4 | defaultPaginationModel | prop
The pagination model for the Grid, which encapsulates current page, sort column id, and sort ascending/descending. If not bound, a persistent property of the Grid is used. When rendering the Grid in a loop, this should be bound in some way to keep successive instances of the Grid configured individually.
renderTableIfEmpty | boolean |  |  | prop
If true, then the Grid will also render a table element complete with headers if the data source is empty. If set to true, a model parameter will have to be specified. A default model for a specific class can be created using BeanModelSource#createDisplayModel(Class, org.apache.tapestry5.commons.Messages).
reorder | String |  |  | literal
A 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. This parameter is only used when a default model is created automatically.
row | Object |  |  | prop
Used 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.
rowClass | String | Not Cached |  | prop
Parameter used to set the CSS class for each row (each tr element) within the tbody). This is not cached, so it will be recomputed for each row.
rowIndex | int |  |  | prop
Optional output parameter (only set during rendering) that identifies the current row index. This is the index on the page (i.e., always numbered from zero) as opposed to the row index inside the org.apache.tapestry5.grid.GridDataSource.
rowsPerPage | int |  | symbol:tapestry.components.grid_rows_per_page | prop
The 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.
sortModel | org.apache.tapestry5.grid.GridSortModel |  |  | prop
The 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.
source | org.apache.tapestry5.grid.GridDataSource | Required |  | prop
The source of data for the Grid to display. This will usually be a List or array but can also be an explicit GridDataSource. For Lists and object arrays, a GridDataSource is created automatically as a wrapper around the underlying List.
volatile | boolean |  |  | prop
If true and the component is enclosed by a Form, then the normal state saving logic is turned off. Defaults to false, enabling state saving logic within Forms. This can be set to false when form elements within the Grid are not related to the current row of the grid, or where another component (such as org.apache.tapestry5.corelib.components.Hidden) is used to maintain row state.

### 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
      {
          @NonVisual
          private long id;

          private String firstName;

          private String lastName;

          private int age;

          public long getId() { return id; }

          public void setId(long id) { this.id = id; }

          public String getFirstName() { return firstName; }

          public void setFirstName(String firstName) { this.firstName = firstName; }

          public String getLastName() { return lastName; }

          public void setLastName(String lastName) { this.lastName = lastName; }

          public int getAge() { return age; }

          public void setAge(int age) { this.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_4.xsd" xmlns:p="tapestry:parameter">
          <body>
              <h1>List Users</h1>

              <t:grid source="users" row="user">
                  <p:lastNameCell>
                      <t:pagelink page="user/view" context="user.id">${user.lastname}</t:pagelink>
                  </p:lastNameCell>
                  <p:empty>
                    <p>There are no users to display; you can <t:pagelink page="user/add">add some</a>.</p>
                  </p:empty>
              </t:grid>
          </body>
      </html>

  The block 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 element, and the provided block parameter provides the content inside the .

  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 element. The provided block is responsible for providing any links or icons related to sorting.

  Binding the Grid's empty parameter overrides the default message displayed when there is no data to display. As demonstrated above, it doesn't have to be simple text, the block can be a snippet of markup and components.

  ### UserList.java

      public class UserList
      {
          @Inject
          private UserDAO userDAO;

          @Property
          private User user;

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

  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

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

              <t:grid source="users" row="user" add="delete">
                  <p:lastnamecell>
                      <t:pagelink page="user/view" context="user.id">${user.lastname}</t:pagelink>
                  </p:lastnameCell>
                  <p:deletecell>
                      <t:actionlink t:id="delete" context="user.id">Delete</t:actionlink>
                  </p:deletecell>
                  <p:empty>
                    <p>There are no users to display; you can <t:pagelink page="user/add">add some</a>.</p>
                  </p:empty>
              </t:grid>
          </body>
      </html>

  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 virtual property because it doesn't correspond to a property of the data object, User.

  ### UserList.java

      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);
          }
      }

  The only addition here is an event handler method for when the delete link is clicked.

  ### 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.

### Overriding Columns in Java

  In the previous example, we explained how to override the rendering block of an attribute, by using a Block object in the template. In this part, we will see how can we do the same thing in the Java class.

  ### UserList.tml

  The Grid has a PropertyOverrides parameter, which makes it possible to override the rendering block directly in the Java Class, thanks to its getOverrideBlock method. This method takes one parameter, the name of the block you want to override. We will use the same suffixes (Cell and Header).

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

              <t:grid t:source="users" t:overrides="propertyOverrides">

              </t:grid>
          </body>
      </html>

  ### UserList.java

  But the next question is "How to render a Block in Java ?". We will use the RenderableAsBlock class, which will convert a simple Renderable into a Block. We will use the MarkupWriter object of the render method for writing the content of the Block.

      public class UserList
      {
          @Inject
          private UserDAO userDAO;

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

          void getPropertyOverrides()
          {
              return new PropertyOverrides() {

                  public Messages getOverrideMessages() {
                      // TODO Auto-generated method stub
                      return null;
                  }

                  public Block getOverrideBlock(String name) {

                     if(name.equalsIgnoreCase("firstNameHeader")){
                          return new RenderableAsBlock(new Renderable() {

                              public void render(MarkupWriter writer) {
                                  writer.write("test override");
                              }
                          });
                      }

                      return null;
                  }
          }
      }

  In this example, we have just changed the header of the firstName attribute.

### 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 ,

  and elements, it generates data 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.
  data-grid-property="property"
    Added to
  elements to allow customization of a particular column's header, and added to elements to allow customization of a particular column's data cells.
data-grid-column="first"
  Added to the first .
data-grid-row="first"
  Added to the first
  of the
  (the data portion of the table).
data-grid-column="last"
  Added to the last .
data-grid-row="last"
  Added to the last
  .
data-grid-column-sort="ascending"
  Added to the and all corresponding elements for the column that is the current sort column (if any, for ascending sort).
data-grid-column-sort="descending"
  Identifies cells of the sort column for descending..

The added attributes can get quite verbose; the Grid's lean parameter allows the data-grid-property attribute to be omitted. Even in lean mode, the other attribute values are rendered.

### Configuring the Grid Component in the AppModule class

It is possible to configure the rowsPerPage, pagerPosition and tableClass parameters of the Grid component in the AppModule class of your application. All your Grid components will use this default configuration until you define a value for one of these parameters.

    public static void contributeApplicationDefaults(MappedConfiguration<String, String> configuration)
    {
      configuration.add(ComponentParameterConstants.GRID_ROWS_PER_PAGE, "25");

      configuration.add(ComponentParameterConstants.GRID_PAGER_POSITION, "top");

      configuration.add(ComponentParameterConstants.GRID_TABLE_CSS_CLASS, "table table-hover table-bordered table-striped");
    }

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `Grid()`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `protected Binding`
  `defaultModel()`
  Returns a `Binding` instance that attempts to identify the model from the source parameter (via `GridDataSource.getRowType()`.
  `String`
  `getClientId()`
  `int`
  `getCurrentPage()`
  `BeanModel`
  `getDataModel()`
  Returns the data model, which defines the columns (in terms of properties of the row type), and provides access to actual values for a given row instance.
  `GridDataSource`
  `getDataSource()`
  Returns the source for the data to be presented in the Grid.
  `GridPaginationModel`
  `getDefaultPaginationModel()`
  `int`
  `getNumberOfProperties()`
  `Object`
  `getPagerBottom()`
  `Object`
  `getPagerTop()`
  `Object`
  `getRow()`
  `int`
  `getRowsPerPage()`
  `GridSortModel`
  `getSortModel()`
  Returns the object used to track sorting behavior of the Grid.
  `void`
  `reset()`
  Resets the Grid to inital settings; this sets the current page to one, and clears the sort model.
  `void`
  `setCurrentPage(int currentPage)`
  `void`
  `setRow(Object row)`

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Constructor Details

  - ### Grid

    public Grid()

- ## Method Details

  - ### defaultModel

    protected Binding defaultModel()
    Returns a `Binding` instance that attempts to identify the model from the source parameter (via `GridDataSource.getRowType()`. Subclasses may override to provide a different mechanism. The returning binding is variant (not invariant).
    See Also:
      - `BeanModelSource.createDisplayModel(Class, org.apache.tapestry5.commons.Messages)`

  - ### getDefaultPaginationModel

    public GridPaginationModel getDefaultPaginationModel()

  - ### getDataModel

    public BeanModel getDataModel()
    Description copied from interface: `GridModel`
    Returns the data model, which defines the columns (in terms of properties of the row type), and provides access to actual values for a given row instance.
    Specified by:
      `getDataModel` in interface `GridModel`

  - ### getNumberOfProperties

    public int getNumberOfProperties()

  - ### getDataSource

    public GridDataSource getDataSource()
    Description copied from interface: `GridModel`
    Returns the source for the data to be presented in the Grid.
    Specified by:
      `getDataSource` in interface `GridModel`

  - ### getSortModel

    public GridSortModel getSortModel()
    Description copied from interface: `GridModel`
    Returns the object used to track sorting behavior of the Grid.
    Specified by:
      `getSortModel` in interface `GridModel`

  - ### getPagerTop

    public Object getPagerTop()

  - ### getPagerBottom

    public Object getPagerBottom()

  - ### getCurrentPage

    public int getCurrentPage()

  - ### setCurrentPage

    public void setCurrentPage(int currentPage)

  - ### getRowsPerPage

    public int getRowsPerPage()

  - ### getRow

    public Object getRow()

  - ### setRow

    public void setRow(Object row)

  - ### reset

    public void reset()
    Resets the Grid to inital settings; this sets the current page to one, and clears the sort model.

  - ### getClientId

    public String getClientId()
    Specified by:
      `getClientId` in interface `ClientElement`
    Returns:
      a unique id for the element. This value will be unique for any given rendering of a page. This value is intended for use as the id attribute of the client-side element, and will be used with any DHTML/Ajax related JavaScript.