The ICEfaces Tutorial
Table of Contents


Lesson: Using the columns component

How to Use the ICEfaces Columns Component

The columns component can be used to display unique or repeating information backed by a row and column model in a dataTable. Basically by linking the front end columns component directly to a bean level model, the developer has greater control over the contents of their tables.

The columns component can be used as a replacement for the standard h:column child of a standard dataTable. The following screenshot is of the ice:columns component demo in the component-showcase. Notice the ability to increase or decrease the number of columns displayed.

columns component in Component Showcase application

To use the full potential of the columns component, a DataModel for the rows and columns should be specified in a backing bean. Through the DataModels, the developer can specify the information that will be present in the table.

The rest of this tutorial will discuss the following topics:

Creating a Basic Columns table

The creation of a basic columns component with custom non-changing data is a simple 3 step process.

  1. Create a String list for rows and columns
  2. Wrap each list in a DataModel
  3. Bind the DataModels to the page level dataTable and columns
In this next example the page contains a numbered list of repeating Odd and Even values.

The backend DataModels are created through the above process. Example code from the demo bean would be similar to:

    private String[] index = {"1.", "2.", "3.", "4."};
    private String[] heading = {"Odd", "Even"};
    private DataModel rowModel = new ArrayDataModel(index);
    private DataModel columnsModel = new ArrayDataModel(heading);

Once the backend objects have been created, they must be bound to the page level dataTable and columns. This is done through the value attribute of the component, as shown below:

    <ice:dataTable value="#{backing.rowModel}" var="row">
        <ice:column>
            <ice:outputText value="#{row}"/>
        </ice:column>
        <ice:columns value="#{backing.columnsModel}" var="col">                                        
            <ice:outputText value="#{col}"/>
        </ice:columns>
    </ice:dataTable>

As you can see, the row DataModel is assigned to the parent dataTable, and the columns DataModel as a value of the ice:columns component. By using a var declaration, we can output the current value of the DataModel as the component is iterated through during the rendering process.

The example page uses the above data for the rows and columns, as well as some minor styling. When viewed, it appears similar to:

Basic Columns Example

Download demo:

The DataModels used in the backing are simple to create, and the next tutorial will demonstrate calculating page level information from the status of the backend objects.

Creating a Cross Columns table

This example will create another columns component, but without the use of static data. Instead the each row will be filled with color coded true / false values for each web browser. The finished product will look similar to:

Cross Columns Example

The page level changes are minimal, the main addition is of the color coded value instead of a plain row / column output. This is achieved through a situational outputText, as shown below:

    <ice:outputText value="#{backing.supportInfo}" style="color:#{backing.supportInfo eq 'true'?'green':'red'};"/>

Basically we apply either a red or green CSS font color depending on the status of the supportInfo variable in the backing bean. When we look at the backing bean for this example, the power of linking the columns component to a DataModel becomes apparent. The getSupportInfo method is the main change since the last example, and contains code similar to the following:

    public Object getSupportInfo(){
        DataModel rowDataModel = getRowModel();
        if (rowDataModel.isRowAvailable())
        {
          Object event = getRowModel().getRowData();
          DataModel columnsDataModel = getColumnsModel();
          if (columnsDataModel.isRowAvailable())
          {
            Object browser = columnsDataModel.getRowData();
            return eventSupport.get(event+browser.toString());
          }
        }
        return null;
    }

The above method will use the current row and column DataModel to retrieve the support information for that index. Basically we get the current row, ensure it is available (which means the page has loaded it, the component is rendered, etc.), and then do the same for the column. With the combined row / column data, we can check the support info string and return a proper result to the page.

Download the demo:

So far the examples use static data that does not change one generated. The next tutorial will detail how columns data can be updated from the backend.

Creating an Updating Columns table

Similar to the previous examples, an updating columns component uses the same initial approach to the setup of pages and beans. The only difference is we will add a commandButton that will cause variables in the backing bean to change. This is reflected on the page as:

    <ice:commandButton value="Update" actionListener="#{backing.next}"/>

Then the method called from this page level commandButton will need to be added to the backing bean. The goal of the button was to force the data in the columns component to update, and so the next() method will simply increase an integer (which will later be added to the page so the changes can be seen).

    public void next(ActionEvent event) {
        startFrom += 1+randomizer.nextInt(4);
    }

As you can see the created method is very simple, basically adding a small random number to the startFrom integer. To allow the user to see the changes when they press the 'Update' button, the startFrom value will be displayed inside a columns component in the page, as shown below:

    <ice:columns value="#{backing.columnsModel}" var="headings">                                        
        <f:facet name="header">
            <h:outputText value="#{headings}" />
        </f:facet>
        <ice:outputText value="#{backing.startFrom}"/>
    </ice:columns>

The end result is that when the user presses the 'Update' button, the next() method is called, which updates an integer. The changed value is automatically displayed as the contents of a column component. Using this basic understanding, it's possible for a developer to update statistics from a real time persistence layer, etc.

When the above elements have been added, a page similar to the following is created:

Updating Columns Example

Download the demo:

As was shown, updating the data contents of a columns component was simple. But a developer may also wish to modify the attributes of the columns on the fly, which will be demonstrated in the next example.

Creating a Dynamic Columns table

Due to the coupling of a flexible DataModel and powerful front end columns component, a developer has the option to dynamically modify not only the contents of the table, but also the attributes of the component. To demonstrate this, we will look in detail at allowing the user to increase or decrease the number of columns present on the page.

The first step is to add a friendly message and input field for the new number of columns. Alternatively a select input component or similar element could be used on the page. In addition standard JSF validators could be attached to the input, as compared to the rudimentary method of performing backend level checks. An example of the use prompt and input field used is given below:

    <ice:outputText value="Enter the number of columns to display (between 1 to 8)"/>
    <ice:inputText value="#{backing.numberOfColumns}" valueChangeListener="#{backing.change}"/>

Next we will need to fill in the change() method that will be called when the value inside the inputText component is changed. The overall purpose of this method is to ensure a valid number of columns was entered, and if present then update the existing columns component to reflect the new count. This update will be done through modifying the backend DataModel, which will be shown in detail later. For now, an example of what the change() method would look like follows:

    public void change(ValueChangeEvent event) {
        int columnValue = (event.getNewValue() != null ?
            Integer.parseInt(event.getNewValue().toString()) : 7);
            
        if ((columnValue >= 1) && (columnValue <= 8)) {
            numberOfColumns = columnValue;
            updateModel();
        }
    }

As you can see, the bean handles validation instead of the page (again, this is just for simplicity). If the new number of columns is valid, we store it in the session bean and update the DataModel, through the self explanator updateModel() method. The contents of this method would be similar to the following:

    public void updateModel() {
        String[] array = new String[numberOfColumns];
        for (int i = 0; i < numberOfColumns; i++) {
            array[i] = String.valueOf(i+1);
        }
        columnsModel = new ArrayDataModel(array);
    }

Basically, we take the newly updated numberOfColumns variable and recreate the columns DataModel, with numbers inserted for each line of header text.

When the above steps have been implemented, an application similar in appearance to the following would be produced:

Dynamic Columns Example

You may have noticed a very nice benefit of using the columns component in this way is that the backend is all that needs to be modified, the page level component itself hasn't changed much beyond the first example. This makes the many available changes to the DataModel a useful option to avoid having to update several pages.

Download the demo:

Examples Using Columns

Example Source Notes
Component Showcase Available in release bundles Columns example which with alphabetical data in a dynamically sizeable columns based table.
columns-basic columns-basic source code Simple example of how to setup a basic hard coded columns component.
columns-cross columns-cross source code Example showing how to insert custom on the fly data into a columns component.
columns-dynamic columns-dynamic source code Demonstration of how the size and number of columns can be dynamic modified.
columns-update columns-update source code This example shows how the data inside a columns component can be updated to reflect user initiated changes.

The ICEfaces Tutorial
Table of Contents

Copyright 2006 ICEsoft Technologies Inc. All rights reserved.