Thursday, June 23, 2011

Generate a table in JSF by iterating over a List

The problem


If you want to create a table in JSF, there are two tags you can use: the <h:panelGrid> and the <h:dataTable> tags. In the first tag, you specify the number of columns (using the colums attribute), and JSF will automatically put each child component of the panelGrid tag in a new column. When the number of columns you specified is reached, a new row will start.
The dataTable component works differently: this component needs <h:column> child components for each column in your table.
Another major difference between the two components is that the dataTable component can iterate over a collection (using the value and var attributes), while the panelGrid cannot.
In my case, I had a List of products in my backing bean. I wanted to display them in a table, 3 products per row. The panelGrid component would have been perfect for this, except that it cannot iterate over a List. I couldn't use the dataTable component either, since this component expects column child elements.

The solution

Since I couldn't use the dataTable or the panelGrid components, I decided to create my own table using the <ui:repeat> tag. This tag allows you to iterate over a collection, specifying whatever code you want in the tag body.
The only thing that remained was to show 3 products per row. Fortunately the repeat tag has a varStatus attribute, which we can use to query the index we're at.
This is the final code:
<table>
  <tr>
    <ui:repeat var="product" value="#{productBean.products}" varStatus="status">
      <f:verbatim rendered="#{status.index mod 3 == 0}">
        &lt;/tr&gt;&lt;tr&gt;
      </f:verbatim>
      <td>#{product.name}</td>
    </ui:repeat>
  </tr>
</table>