How to Use the ICEfaces Data Table ComponentsThe 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: 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
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 the inventory array constructor in the Table bean class: TableBean.java // 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 carInventory Object. This is important as the assigned carInventory Array will be 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 an 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 first step in adding a dataPaginator control component to a dataTable is to ensure that the dataTable has a unique id attribute 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 dataTable's 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 maximum number of pages controls 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 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 dataTable's 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 variable names to the dataTable model:
The following code shows how bound user defined variables can be used to display the dataTable's 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>
Adding a Sortable Header
In this section we will add a commandSortHeader component to each inventory column shown in the previous example. The first step in this process is to modify the TableBean backing bean by extending SortableList.java. The SortableList class is provided for convenience but its functionality 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 attribute's boolean value is toggled if the same commandSortHeader is activated. The following JSF code snippet shows 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 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 commandSortHeader in this example wraps the output text for the header and adds an arrow which will indicate the ordering applied to the table data. To help avoid typing errors the 'columnName' attribute is bound to the backing bean, the column name is used to specify which column should be sorted. 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 component's sortColumn and sortAscending attributes and as a result it is up to the table's backing bean to use this information to provide sorted data. The following sort method shows how we sort the dataTable data. Remember that sortColumn is bound to the sortColumnName property and that sortAscending is bound to the ascending property in the TableBean class. TableBean.java 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 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: TableBean.java 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 shown 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 customize the dataTable with CSS.
Customising the Data Table CSS style
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 classes 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 the first defined style and so on. 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. style.css /* 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 the columnClasses attribute by the dataTable renderer. 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. The dataTable renders an 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 ICEfaces' predefined CSS names. These names are as follows:
Tutorial Source Code Downloads
|
Data Table
© Copyright 2021 ICEsoft Technologies Canada Corp.