Data Table

compared with
Version 9 by Feras Nasser
on Nov 01, 2012 19:39.


Key
These lines were removed. This word was removed.
These lines were added. This word was added.

View page history


There are 2 changes. View first change.

 h1. 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:
  
 !dataTable-webmail_screenshot.png!
  
 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.
  
 ----
 \\
 {panel}This tutorial will discuss the following topics related to the use of the dataTable component:
  
 * [Creating a Simple Table|#table]
 * [Adding a Data Paginator|#paginator]
 * [Adding a Sortable Header|#sortable]
 * [Customizing the Data Table CSS style|#style]
 * [Tutorial Source Code Downloads|#downloads]
 {panel}
 \\
 ----
  
 [!icefaces-services-wiki.png|align=center!|http://www.icesoft.org/java/services/icefaces-professional-services.jsf]
  
 h3. {anchor:table}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.
  
 !dataTable-basic_screenshot.png!
  
 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:
  
 {code:title=TableBean.java|borderStyle=solid}
 // 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)};
 {code}
  
 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:
  
 {code:xml}
 <ice:dataTable value="#{inventoryList.carInventory}"
  var="item" >
  ...
 </ice:dataTable>
 {code}
  
 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:
  
 {code:xml}
 <!-- Stock number -->
 <h:column>
  <f:facet name="header">
  <ice:outputText value="Stock #"/>
  </f:facet>
  <ice:outputText value="#{item.stock}"/>
 </h:column>
 {code}
  
 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.
 \\
 \\
 ----
  
 h3. {anchor:paginator}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 works in conjunction with the dataTable component allowing manipulation of the view of the dataTable data model. The following screen shot shows two dataPaginator components; the first provides paging navigation control and the other shows the current state of the dataTable model.
  
 !dataTable-paginator_screenshot.png!
  
 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:
  
 {code:xml}
 <ice:dataPaginator id="dataScroll_3"
  for="inventoryList"
  paginator="true"
  fastStep="3"
  paginatorMaxPages="4">
  ...
 <ice:dataTable rows="5"
  id="inventoryList"
  value="#{inventoryList.carInventory}"
  var="item">
 {code}
  
 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:
  
 {code:xml}
 <f:facet name="first">
  <ice:graphicImage url="./xmlhttp/css/xp/css-images/arrow-first.gif"
  style="border:none;"
  title="First Page"/>
 </f:facet>
 {code}
  
 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:
  
 * _rowsCountVar_ -- number of rows in the dataTable view model.
 * _displayedRowsCountVar_ -- number of rows shown in this dataTable view model.
 * _firstRowIndexVar_ -- index of first row displayed in this dataTable view model.
 * _lastRowIndexVar_ -- index of the last row displayed in this dataTable view model.
 * _pageCountVar_ -- number of pages that make up dataTable view model.
 * _pageIndexVar_ -- current page number in the dataTable view model.
  
 The following code shows how bound user defined variables can be used to display the dataTable's model state:
  
 {code:xml}
 <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>
 {code}
 \\
 \\
 ----
  
 h3. {anchor:sortable}Adding a Sortable Header
 \\
 This tutorial has already shown how easy it is to use the dataTable with the dataPaginator component. It is also possible to add sorting support to the dataTable via 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 commandSortHeader being used in the dataTable-sortable example to sort the inventory by stock number:
  
 !dataTable-sortable_screenshot.png!
  
 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:
  
 {code:xml}
 <ice:dataTable id="dataSortData"
  sortColumn="#{inventoryList.sortColumnName}"
  sortAscending="#{inventoryList.ascending}"
  value="#{inventoryList.carInventory}"
  var="item">
 {code}
  
 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.
  
 {code:xml}
 <!-- 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>
 {code}
  
 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.
  
 {code:title=TableBean.java|borderStyle=solid}
 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);
 }
  
 {code}
  
 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:
  
 {code:title=TableBean.java|borderStyle=solid}
 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;
 }
 {code}
  
 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.
 \\
 \\
 ----
  
 h3. {anchor:style}Customising the Data Table CSS style
 \\
 The ice:dataTable, like most JSF components can be styled using CSS. If no style classes are specified, the component will use a set of default names that are defined in the XP, Royale and Rime 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_.
  
 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.
  
 {code:xml}
 columnClasses="stockColumn, modelColumn, desriptionColumn, odometerColumn, priceColumn"
 {code}
  
 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.
  
 {code:title=style.css|borderStyle=solid}
 /* 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;
 }
 {code}
  
 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.
  
 !dataTable-style_screenshot.png!
  
 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:
  
 ||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.|
 \\
 \\
 ----
  
 h3. {anchor:downloads}Tutorial Source Code Downloads
 \\
 || Example || Source || Notes ||
 | dataTable-basic |[dataTable-basic source code |^dataTable-basic-tutorial.zip|Download Source Code]| Simple example of how to dispaly data uses a dataTable component. |
 | dataTable-paginator |[dataTable-paginator source code |^dataTable-paginator-tutorial.zip|Download Source Code]| A dataPaginator is added to the dataTable used in dataTable-basic |
 | dataTable-sortable |[dataTable-sortable source code |^dataTable-sortable-tutorial.zip|Download Source Code]| CommandSortHeaders are added to each column in a data table. |
 | dataTable-style |[dataTable-style source code |^dataTable-style-tutorial.zip|Download Source Code]| The row and column classes are altered with CSS. |
  
 [!icefaces-services-wiki.png|align=center!|http://www.icesoft.org/java/services/icefaces-professional-services.jsf]

© Copyright 2017 ICEsoft Technologies Canada Corp.