The ICEfaces Tutorial
Table of Contents


Lesson: Using the data table component

How to Use the ICEfaces Data Table Components

The dataTable component can display Objects in a Collection or an Array where each Object represents one row in the table and columns match instance variables in the Object. This mapping is achieved through the JSF attribute iterator pattern of value and var and introspection. The dataTable can limit the number of rows it displays and CSS styles can be applied to both rows and columns. The following is a screen shot of a fully implemented dataTable within the Webmail application:

Data Table component in Webmail Application

DataTable functionality can be greatly extended when combined with the commandSortHeader and dataPaginator components. The commandSortHeader component allows column based sorting by clicking on a column header. The dataPaginator component allows the display of only a small portion of a large dataset. The dataPaginator also provides methods for navigating through the dataset while maintaining the same view size. The dataTable renders an HTML table and the underlying DataTable model can define table header, body and footers which map to theader, tbody and tfooter HTML tags.

This tutorial will discuss the following topics related to the use of the dataTable component:

 

Creating a Simple Table

Creating a dataTable is fairly straight forward process, all that is needed is a backing been containing a Collection or Array. Here is a picture of a rendered dataTable in the dataTable-basic demo.

Basic dataTable Example

Download the demo:

The backing bean in this example contains an array of nineteen InventoryItem objects. Each InventoryItem object represents one row in the rendered dataTable component. Each column in the rendered dataTable component represents an instance variable in the InventoryItem object. The following code shows how the inventory array constructor in the Table bean class:

    // List of sample inventory data.
    private InventoryItem[] carInventory = new InventoryItem[]{
    new InventoryItem(58285, "Dodge Grand Caravan", " Sto&Go/Keyless", 43500,
    21695),
    ...
    new InventoryItem(58275, "Dodge Dakota Q.C. SLT", "4x4/Loaded/Alloys",
    22500, 27995),
    new InventoryItem(58265, "Chrysler 300 Touring", "Heated Leather", 40500,
    26495)
    };

The dataTable components value attribute is assigned to the carInventorty Object. This is important as the assigned carInventory Array will iterated by the variable defined by the var attribute in the dataTable component. The following JSF code shows how the inventory list is assigned to the dataTable:

    <ice:dataTable
    value="#{inventoryList.carInventory}"
    var="item" >
    ...
    </ice:dataTable>

Columns in a dataTable are defined by the column component. Each column can be bound to a instance variable defined by the var attribute in the dataTable declaration. The following JSF code shows how the first column of the table will be defined:

    ...
    <!-- Stock number -->
    <h:column>
        <f:facet name="header">
            <ice:outputText value="Stock #"/>
        </f:facet>
        <ice:outputText value="#{item.stock}"/>
    </h:column>
    ...

The column declaration in the above code block has an optional facet declaration. This facet can be named either ?footer? or ?header? and renders the child components in either a theader or tfooter in the rendered HTML table. Any column subcomponents that are not in the named facet will be rendered as row data for the particular column being rendered. In this example we saw how the dataTable component can be used to quickly display data collections. In the next section a dataPaginator component will be added to the dataTable.

 

Adding a Data Paginator

The dataTable component is good at displaying large set of data but there are many user interface (UI) scenarios where only a limited subset of the data can or should be shown. The dataPaginator component work in conjunction with the dataTable component allows for the manipulation and view of the dataTable data model. The following screen shot shows two dataPaginator components; the first provides paging navigation control and the other show the current state of the dataTable model.

Paginator dataTable Example

The first step in adding a dataPaginator control component for a dataTable is to ensure that the dataTable has a unique id attributes assigned to it and that the number of rows in a page view is set via the rows attribute. The dataPaginator components for attribute is then set to the dataTable id value, this binds the dataPaginator to the dataTables model. The next step in adding a dataPaginator is to set the attribute paginator to true, this insures that the control links around defined facet controls will be rendered. The following JSF code snippet is of a dataPaginator control where the fastforward and fastrewind facets will move ahead three pages and the maxim number of pages controls that are shown at the same time is set to four:

    <ice:dataPaginator id="dataScroll_3"
        for="inventoryList"
        paginator="true"
        fastStep="3"
        paginatorMaxPages="4">
            ...
            <ice:dataTable
                rows="5"
                id="inventoryList"
                value="#{inventoryList.carInventory}"
                var="item">
    ...

The next step in adding a dataPaginator is to is to define the facets which will add control links to their child components. There are are six facets which can be optionally implemented; first, last, previous, next, fastforward and fastrewind. The following is the JSF code needed add a ?first? facet which will allow users to click on an image graphic to move to the first page of the dataTable model:

    <f:facet name="first">
        <ice:graphicImage
            url="./xmlhttp/css/xp/css-images/arrow-first.gif"
            style="border:none;"
            title="First Page"/>
    </f:facet>

The dataPaginator can also be used for displaying information about the dataTables model by setting the paginator attribute to false (default value). There are several attributes on the dataPaginator component which allow a developer to bind user defined variables names to the dataTable model. The data biddable attributes are as follows:

The following code shows how bound user defined variables can be used to display the dataTables model state:

    <ice:dataPaginator id="dataScroll_2" for="inventoryList"
            rowsCountVar="rowsCount"
            displayedRowsCountVar="displayedRowsCount"
            firstRowIndexVar="firstRowIndex"
            lastRowIndexVar="lastRowIndex"
            pageCountVar="pageCount"
            pageIndexVar="pageIndex">
        <ice:outputFormat
                styleClass="standard"
                value="{0} cars found, displaying {1} car(s), from {2} to {3}. Page {4} / {5}.">
            <f:param value="#{rowsCount}"/>
            <f:param value="#{displayedRowsCount}"/>
            <f:param value="#{firstRowIndex}"/>
            <f:param value="#{lastRowIndex}"/>
            <f:param value="#{pageIndex}"/>
            <f:param value="#{pageCount}"/>
        </ice:outputFormat>
    </ice:dataPaginator>

Download the demo:

 

Adding a Sortable Header

This tutorial has already show how easy it is to use the dataTable with the dataPaginator component. It is also possible to add sorting support to the dataTable via the commandSortHeader. The commandSortHeader component adds a commandLink to the dataTable header which when clicked will toggle the ordering of the parent column data. The commandSortHeader can be added to all or just of few dataTable headers. The following screen shot shows the commSortHeader being used in the dataTable-sortable example to sort the inventory by stock number.

Sortable dataTable Example

In this section we will add a commandSortHeader component to each inventory column shown in the previous examples. The first step in this process is to modify the TableBean backing bean by extending the SortableList.java. The SortableList class is provided for convenience but its functionally could just as easily be added to the base class.

The first step in adding a commandSortHeader is to add the attributes sortColumn and sortAscending to the dataTable component. These two attributes provide bindings which are manipulated when a commandSortHeader is activated. The sortColumn attribute is updated to the column name of the selected commandSortHeader and the sortAscending attributes boolean value is toggled if the same commandSortHeader is activated. The following JSF code snip snows the modified dataTable decoration:

    <ice:dataTable
        id="dataSortData"
        sortColumn="#{inventoryList.sortColumnName}"
        sortAscending="#{inventoryList.ascending}"
        value="#{inventoryList.carInventory}"
        var="item">

The next step in updating the dataTable for the commandSortHeader component is to add the component to the a column header facet. The following code shows the addition of a commandSortHeader component to the first column.

    <!-- Stock number -->
    <ice:column>
        <f:facet name="header">
            <ice:commandSortHeader
                    columnName="#{inventoryList.stockColumnName}"
                    arrow="true" >
                <ice:outputText value="#{inventoryList.stockColumnName}"/>
            </ice:commandSortHeader>
        </f:facet>
        <ice:outputText value="#{item.stock}"/>
    </ice:column>

The commandSotHeader in this example wraps the output text for the header and adds an arrow which will indicated the ordering applied to the table date. To help avoid typing errors the column Name is bound to the backing bean, the column name is used to specify which column should be sorted.

Download the demo:

Now that all the JSF code is in place there is still a little work to be done to the backing bean to get the data sorted. As mentioned earlier the commandSortHeader component only manipulates the dataTable components sortColumn and sortAscending attributes and as a result it is up to the tables backing bean to use this information to provide a sorted data. The following sort method show how we sort the dataTable data, remember that sortCoumn is bound the sortColumnName Bean value and the sortAscending is bound to the ascending Bean in the TableBean class.

    protected void sort() {
        Comparator comparator = new Comparator() {
            public int compare(Object o1, Object o2) {
                InventoryItem c1 = (InventoryItem) o1;
                InventoryItem c2 = (InventoryItem) o2;
                if (sortColumnName == null) {
                    return 0;
                }
                if (sortColumnName.equals(stockColumnName)) {
                    return ascending ?
                    Integer.valueOf(c1.getStock()).compareTo(Integer.valueOf(c2.getStock())) :
                    Integer.valueOf(c2.getStock()).compareTo(Integer.valueOf(c1.getStock()));
                } else if (sortColumnName.equals(modelColumnName)) {
                    return ascending ? c1.getModel().compareTo(c2.getModel()) :
                    c2.getModel().compareTo(c1.getModel());
                } else if (sortColumnName.equals(descriptionColumnName)) {
                    return ascending ? c1.getDescription().compareTo(c2.getDescription()) :
                    c2.getDescription().compareTo(c1.getDescription());
                } else if (sortColumnName.equals(odometerColumnName)) {
                    return ascending ?
                    Integer.valueOf(c1.getOdometer()).compareTo(Integer.valueOf(c2.getOdometer()))
                    :
                    Integer.valueOf(c2.getOdometer()).compareTo(Integer.valueOf(c1.getOdometer()));
                } else if (sortColumnName.equals(priceColumnName)) {
                    return ascending ?
                    Integer.valueOf(c1.getPrice()).compareTo(Integer.valueOf(c2.getPrice())) :
                    Integer.valueOf(c2.getPrice()).compareTo(Integer.valueOf(c1.getPrice()));
                }  else return 0;
            }
        };
        Arrays.sort(carInventory, comparator);
    }

When a commandSortHeader is selected form the JSF lifecycle is called and the dataTable values will be retrieved from the backing bean. It is during this dataTable retrieval that the data should be sorted but only if the sortColumnName and sortAscending values have changd. The following code snippet shows the getCarInventory() method has been modified to only sort the array data when required:

    public InventoryItem[] getCarInventory() {
        // we only want to sortColumnName if the column or ordering has changed.
        if (!oldSort.equals(sortColumnName) ||
            oldAscending != ascending){
            sort();
            oldSort = sortColumnName;
            oldAscending = ascending;
        }
        return carInventory;
    }

In this tutorial we have show how to add sortable data columns to a dataTable and when combined with the comandSortHeader the dataTable becomes a very flexible and powerful component. The next and last section of this tutorial will take a look at how to customized the dataTable with CSS.

 

Customising the Data Table CSS style

The dataTable like most JSF components can be styled using CSS. If now style classes are specified, the component will use a set of default names that are defined in the XP or Royale CSS sheets. The default style sheet implementation provides header background images and basic border colours. In this part of the tutorial will will focus on two style attributes, columnClasses and rowClasses.

Download the demo:

The columnClasses attribute can take one or more CSS class names separated by commas. These classes are then iterated over the total number of columns in the table. For example, if there are six columns in a table and two CSS style class defined in the columnClasses attribute then the first column will be given the first defined column style, the second column will be given the second defined column, the third column will be given first defined style and so on an so forth. The iterative style assignment can be quite useful for applying column specific styles to either highlight even and odd columns are to give a particular column specialized styling such as text-alignment. The following code snippet shows how we will define the columnClasses attribute for this example.

    columnClasses="stockColumn, modelColumn, desriptionColumn, odometerColumn,
    priceColumn"

We will be specifying a custom style for each of the five columns. The following code is the CSS that defines the five column styles.

    /* common to all columns*/
    .stockColumn, .modelColumn, .desriptionColumn, .odometerColumn,
    .priceColumn{
    border-right: 1px solid #666666;
    border-bottom: 1px solid #666666;
    }

    .stockColumn{
    width: 60px;
    }

    .modelColumn{
    width: 225px;
    }

    .desriptionColumn{
    width: 150px;
    }

    .odometerColumn{
    width: 75px;
    }

    .priceColumn{
    width: 75px;
    }

The rowClasses attribute is used the same way as thecolumnClasses attribute by the dataTable render. Instead of specifying a style class for each row we will specify two style classes which will be applied to every odd then even row of the dataTable. The following screen shot shows what the dataTable looks like with both columnClasses and rowClasses decorations.

Styled dataTable Example

The dataTable renders a HTML table as the main construct for the rendered dataTable component. The styleClass attribute value will be rendered as a class attribute for the rendered table. If you wish to change the default header styles you must override predefined CSS names. These names are as follows:

CSS Class Name Description
iceTblHeader Default CSS class name applied to all table header cells.
iceTblHeader a Default CSS style applied anchor tags in a table header cell.
 

Examples that Use DataTables

Example Source Notes
Component Showcase Available in release bundles Contains three basic dataTable examples. Also contains an example of a colapsible table that uses a dataTable
Webmail Available in release bundles DataTable is used to display email messages contained in a folder. Also used to dispaly task and contact data.
dataTable-basic dataTable-basic source code Simple example of how to dispaly data uses a dataTable component.
dataTable-paginator dataTable-paginator source code A dataPaginator is added to the dataTable used in dataTable-basic<./td>
dataTable-sortable dataTable-sortable source code CommandSortHeaders are added to each column in a data table.
dataTable-style dataTable-style source code The row and column classes are altered with CSS.

The ICEfaces Tutorial
Table of Contents

Copyright 2006 ICEsoft Technologies Inc. All rights reserved.