<x:columns/>

The columns tag can be used within a x:datatable component to create a dynamic count of columns.

Usage and functionality

Content of a page

...
<x:datatable var="row" value="#{data.rows}">
  <h:column>
    ...
  </h:column>
  ...
  <x:columns var="column" value="#{data.columns}">
    <f:facet name="header">
      <h:outputText value="#{column.header}"/>
    </f:facet>
    <h:outputText value="#{column.value}"/>
    ...
  </x:columns>
</x:datatable>

Use the columns component on the same level as the column component. Columns is a UIData component and accepts for attribute value everything which is accepted by UIData: Arrays, Lists, Collections and instances of DataModel may be used. Define a variable through the var attribute which can be used to reference the current column. Unlike the row in datatable it is allowed to use the column var in headers and footers.

Implementation for data bean

public class Data implements RowHolder
{
  private DataModel mRows;
  private List mColumns;
 
  public DataModel getRows()
  {
    if(mRows == null)
    {
      mRows = createRowDataModel();
    }
    return mRows;
  }

  public Object getRowData()
  {
    DataModel dataModel = getRows();
    if(dataModel.isRowAvailable())
    {
      return dataModel.getRowData();
    }
    return null;
  }
  
  public List getColumns()
  {
    if(mColumns == null)
    {
      mColumns = createColumns();
    }
    return mColumns;
  }

  private List createColumns()
  {
    List result = new ArrayList();
    result.add(new Column("Col1", this));
    result.add(new Column("Col2", this));
    result.add(new Column("Col3", this));
    // add more columns
  }
}

The data bean wraps the row collection into a DataModel instance. The DataModel instance can be used to determine the current row data object. You may also use Array, List or Collection and take the current row instance from the Variable Binding of the var attribute in the datatable component.

The createColumns method creates the dynamic column objects

Declaration of RowHolder

public interface RowHolder 
{
  public Object getRowData();
}

Implementation for Column

public class Column
{
  private final String mHeader;
  private final RowHolder mRowHolder;

  public Column(String header, RowHolder rowHolder)
  {
    mHeader = header;
    mRowHolder = rowHolder;
  }
  
  public String getHeader()
  {
    return mHeader;
  }

  public String getValue()
  {
    Object rowData = mRowHolder.getRowData();    
    if(rowData != null)
    {
      return rowData.getValue(getHeader());
    }
    return null;
  }
}

The implementation for the column class uses the header to identify which value should be used. The rowholder provides the current row instance during the iteration.

How to show different content depending on the dynamic column

To show or handle different content of the column data use the rendered attribute to enable or disable the compontents:

...
<x:datatable var="row" value="#{data.rows}">
  <h:column>
    ...
  </h:column>
  ...
  <x:columns var="column" value="#{data.columns}">
    <f:facet name="header">
      <h:outputText value="#{column.header}"/>
    </f:facet>
    <h:panelGroup rendered="#{column.booleanValue}">
      <h:selectBooleanCheckBox value="#{column.value}" />      
    </h:panelGroup>
    <h:panelGroup rendered="#{column.stringValue}">
      <h:inputText value="#{column.value}" />
    </h:panelGroup>
  </x:columns>
</x:datatable>

Dynamic_Columns (last edited 2009-09-20 23:01:44 by localhost)