Skip to content

TreeTable 2.x

AlexanderLitus edited this page Aug 12, 2014 · 6 revisions

TOCSTART

TOCEND

The TreeTable component is used to display hierarchical data in a tabular format. It provides flexible configuration of the tree structure and content and supports such advanced features as sorting, interactive filtering, node selection (both multiple and single), keyboard navigation, and dynamic data loading (using Ajax). You can also specify a node preloading mode for expanding TreeTable nodes on the client or server side.


Online Demo

Key Features

Interactive Data Navigation

TreeTable lets the user interactively query the data in virtually any way to meet a wide variety of usage scenarios.

Representing Complex Data Structures

These features allow to represent and provide convenient user interface for displaying complex entity types organized as tree structures, for example in cases where fields are grouped into complex sub-types, or the number of fields (aka columns) is dynamic.

Efficient Data Handling

The following features allow optimizing the network traffic and memory, and allow convenient data source declaration depding on the nature of data.

Flexible Data Visualization

There is a number of ways for customizing how a "raw" data is displayed to address various design requirements.

Specifying the Content

To add the TreeTable component to a page, use the <o:treeTable> tag. To specify the content of the TreeTable, you should configure the tree structure and columns. The tree structure is specified as a hierarchy of objects storing node data. The TreeTable component displays a row for each tree node. Specifying the columns defines how the cell contents are derived from the node data that corresponds to the row which holds this cell.

The tree structure in the TreeTable component can be specified either right in the page or in a backing bean. See the sections Static Tree Structure and Dynamic Tree Structure below for more details.


Columns in the TreeTable component are configured in the way similar to the DataTable configuration, i.e. by nesting appropriate column tags within the <o:treeTable> tag. The TreeTable component supports several column types: <o:column>, <o:treeColumn> and <o:selectionColumn> (for more information, see the section Specifying Columns below). In addition you can specify dynamic number of columns using the <o:columns> tag. Child components of the column tag define the contents of the column cells based on the corresponding row's node data. When the TreeTable component is being rendered, it repeatedly makes current the node data for each row and renders all cells for that row based on the list of columns.

Note that the same child components of a column are rendered in every cell of that column. So in order for these components to display different data for each respective row, you should use a request-scope variable referring to the current row's data (see the next section).

Request-Scope Variables

When specifying child components to be displayed in TreeTable columns, you can use request-scope variables that reference the current row's node parameters. There are four such variables. To use any of them, you should declare its name in the corresponding attribute of the <o:treeTable> tag:

  • var (required) - The name of a request-scope variable under which the current node data is available.
  • nodePathVar (optional) - The name of a request-scope variable under which the full path of the current node is available. This variable has the org.openfaces.component.table.TreePath type. Instances of the TreePath class are used to reference a node in the tree structure by its node value and node values of all its parent nodes.
  • nodeLevelVar (optional) - The name of an integer request-scope variable under which the level number of the current node is available, where "0" corresponds to the top-most level.
  • nodeHasChildrenVar (optional) - The name of a boolean request-scope variable under which the flag indicating whether a node has children is available.

In addition there are two more variables provided to define a cell style condition. These variables are available when specifying the condition for the <o:cell> and <o:cellStyle> tags:

  • columnIndexVar - The name of a request-scope variable under which the column index is available. It is a zero-based integer number.
  • columnIdVar - The name of a request-scope variable under which the column ID ia available. It is a string variable that contains the ID specified in the corresponding column tag.

After their declaration, the variables will be available under the declared names when specifying attribute values in JSP source with EL code. If the value is evaluated by a backing bean method, you can use the org.openfaces.util.Faces.var(String varName) method to retrieve a variable by its name.
Note that the request-scope variables are available only for a limited set of the TreeTable attributes.

<o:treeTable var="nodeObject" nodeLevelVar="nodeLevel">
...
</o:treeTable>
Model Node Objects Requirements

There are two ways of defining the tree structure of the TreeTable component. Either way, the node data objects provided by the tree structure must meet the following requirements:

  • They should be serializable.
  • They should correctly implement the equals and hashCode methods.

If node data objects do not meet these requirements, then each node should provide a "node key" object that must uniquely identify the appropriate node and satisfy the above mentioned requirements. The way node keys are specified depends on the type of the tree structure used. For more information about the tree structure, see the sections Static Tree Structure and Dynamic Tree Structure below.

Static Tree Structure

In a static tree structure, the hierarchy of nodes is defined right in the page within the <o:treeTable> tag. To specify the static structure, you should place the <o:staticTreeStructure> tag into the <o:treeTable> tag. This tag should contain a hierarchy of the <o:treeNode> tags for each node.

The <o:treeNode> tag has two attributes: value (required) and nodeKey (optional). The value attribute specifies the node data object and can be either a value-binding expression that references any object or just a String (as in the example below). If present, the nodeKey attribute specifies the node key object for this node, as described in the section above.

The following example shows the TreeTable component with an explicitly defined hierarchy of nodes.

<o:treeTable var="color">
  <o:staticTreeStructure>
    <o:treeNode value="Colors">
      <o:treeNode value="Warm colors">
         <o:treeNode value="Red"/>
         <o:treeNode value="Yellow"/>
      </o:treeNode>
      <o:treeNode value="Cold colors">
        <o:treeNode value="Blue"/>
        <o:treeNode value="Purple"/>
      </o:treeNode>
    </o:treeNode>
  </o:staticTreeStructure>
  <o:treeColumn>
    <h:outputText value="#{color}">
    </h:outputText>
  </o:treeColumn>
</o:treeTable>
Dynamic Tree Structure

In case of a dynamic tree structure, the nodes are not specified explicitly; instead, you specify the rules of how to retrieve the nodes. This gives you the ability to provide flexible hierarchies of objects from any data source.

To specify a dynamic tree structure, use the <o:dynamicTreeStructure> tag. The hierarchy in the dynamic tree structure is defined by specifying an expression for retrieving child nodes of a given node. This expression is specified using the nodeChildren attribute. Whenever the TreeTable component needs to retrieve a list of children for a specific node, it makes this node current and evaluates the expression specified by the nodeChildren attribute. The parameters of the current node are available in the expression through request-scope variables.

Building of the tree structure starts from retrieving the list of top-level nodes. As with any other nodes, the top-level nodes are calculated with the nodeChildren attribute, but in their case there is no parent node. After retrieving the top-level nodes, the TreeTable component retrieves child nodes for each of them recursively using the same attribute.

The <o:dynamicTreeStructure> tag provides the following attributes:

  • nodeChildren - This is a required attribute that should be defined as a value-binding expression. This expression should provide a list of child node data objects for the parent node. The parent node whose children should be retrieved can be identified through the request-scope variables whose names are specified with the var, nodePathVar, or nodeLevelVar attributes of the <o:treeTable> tag (for more information about these attributes, see the section Request-Scope Variables above). For retrieving top-level nodes, these variables have the following values: var has a value of null, nodePathVar has a value of null, and nodeLevelVar has a value of -1.
  • nodeHasChildren - This is an optional boolean attribute that specifies whether the node has children or not. When the attribute is set, the TreeTable component doesn't calculate the nodeChildren attribute when it's necessary to know whether a node has any children. This defers retrieval of child nodes until they are actually needed and can greatly reduce the time of the tree model retrieval if calculation of the nodeChildren attribute's expression is time-consuming. The nodeHasChildren attribute must be set as a value-binding expression. The node that should be checked for the presence of children can be identified using the same request-scope variables as in the nodeChildren attribute.
  • nodeKey - This attribute defines the key node object if it is required (see the section Model Node Objects Requirements for more details). The node for which the node key should be returned can be identified using the same request-scope variables as in the nodeChildren attribute.

This example shows the TreeTable component that references the Messages backing bean.

<o:treeTable var="message">
  <o:dynamicTreeStructure nodeChildren="#{Messages.nodeChildren}"
                          nodeHasChildren="#{Messages.nodeHasChildren}"
                          nodeKey="#{message.id}"/>
  <o:treeColumn>
    <f:facet name="header">
      <h:outputText value="Subject"/>
    </f:facet>
    <h:outputText value="#{message.subject}"/>
  </o:treeColumn>
  <o:column>
    <f:facet name="header">
      <h:outputText value="Author"/>
    </f:facet>
    <h:outputText value="#{message.author}"/>
  </o:column>
</o:treeTable>

In the following example, you can see a method from the backing bean of the previous example:

public List getNodeChildren() {
    ForumMessage message = Faces.var("message", ForumMessage.class);
    if (message == null)
      return myRootMessages;
    else
      return message.getReplies();
  }

public boolean isNodeHasChildren() { ForumMessage message = Faces.var("message", ForumMessage.class); return message.hasReplies(); }

Specifying Columns

Specifying columns defines the contents of all the cells of the TreeTable component. Each table column defines the content of its header, footer, and body cells. The content for the body cells is specified using row request-scope variables (for more details about them, see the section Request-Scope Variables).

The TreeTable component supports three types of columns:

  • <o:column> - This is a basic column that renders the specified cell contents.
  • <o:treeColumn> - This column shows the hierarchy position of each node by indenting it and also provides controls for expanding/collapsing child nodes (called "expansion toggle button").
  • <o:selectionColumn> - This column shows check boxes for multiple row selection or radio buttons for single row selection. The selection column is an alternative way for the user to change selection and see which row(s) is selected.

The list of columns is specified using the <o:column> tag for each column. The use of the <o:column> tag is the same as for the DataTable component. The content of the <o:column> tag is used for rendering the cells belonging to that column. The column also has the "header", "subHeader" and "footer" facets that can be used to specify its header, sub-header (usually displays filtering component) and footer respectively.

When specifying child components to be displayed in the column, in addition to the variable specified in the var attribute, you can use variables whose names are specified in the nodeLevelVar, nodePathVar or nodeHasChildren attributes of the TreeTable component (see the section Request-Scope Variables for more details). Note that these variables are not mandatory and you can use them as needed.

To specify a column for displaying the tree structure, use the <o:treeColumn> tag. The use of the <o:treeColumn> tag is similar to the <o:column> tag with the exception of some features described below.

The following example shows a two-column TreeTable component with headers for each column.

<o:treeTable var="message">
  <o:dynamicTreeStructure nodeChildren="#{Messages.nodeChildren}" />
  <o:treeColumn>
    <f:facet name="header">
      <h:outputText value="Subject"/>
    </f:facet>
    <h:outputText value="#{message.subject}"/>
  </o:treeColumn>
  <o:column>
    <f:facet name="header">
      <h:outputText value="From"/>
    </f:facet>
      <h:outputText value="#{message.author.userName}"/>
  </o:column>
</o:treeTable>

The <o:treeColumn> tag provides several additional attributes for customizing its appearance and nodes. The levelIndent attribute lets you specify the horizontal offset between the node levels. It can be specified in pixels (px), millimeters (mm), em dashes (em), etc. For example, "30px". The showAsTree boolean attribute ("true" by default) allows you to dynamically change the column appearance. So when the attribute is set to "false", the column looks like an ordinary column specified with the <o:column> tag. The expansionToggleCellStyle and expansionToggleCellClass attributes are used to define a style for a cell that contains expansion toggle (+ and -) buttons. And you can customize expansion toggle images (+/-), using the expandedToggleImageUrl and collapsedToggleImageUrl attributes.


The following example shows the TreeTable component in which the nodes are indented by 30 pixels and a style is applied to the cell with an expansion toggle button:

<o:treeTable var="message">
  <o:treeColumn
    levelIndent="30px"
    expansionToggleCellStyle="vertical-align: top; padding-top: 4px">
    <f:facet name="header">
      <h:outputText value="Subject"/>
    </f:facet>
      <h:outputText value="#{message.subject}"/>
  </o:treeColumn>
</o:treeTable>

Please also read the Specifying Header and Footer section in DataTable documentation for the description of two ways of specifying column's header and footer and a way of specifying column name for bound components such as a composite filter or a column visibility menu.

Specifying Dynamic Columns

In addition to column types listed in section Specifying Columns the TreeTable provides an ability to specify dynamic list of columns. This can be done by adding the <o:columns> child tag to the <o:treeTable> tag. This tag can be used in any place where the ordinary <o:column> tag can be used.

The list of the dynamic columns is specified using the value attribute of the <o:columns> tag. This attribute should be specified as a value-binding expression that refers to an array or a collection of objects that serve as column data objects. The <o:columns> tag results in adding one column per each object found in this collection. The column data objects must be serializable and correctly implement equals and hashCode methods. You should make sure to provide objects that identify their respective columns in any way that should be sufficient for distinguishing between columns when they are rendered or their properties are calculated. See below for the places where column data objects are used. Please note the var request-scope variable of the TreeTable is not available when you specify the value attribute of the <o:columns> tag.

Most of the attributes of <o:columns> tag are analogous to their counterparts in the <o:column> tag but they have one valuable difference – an ability for the attributes to be specified as value binding expressions that allow specifying column attributes on a per-column basis. You need to use the column data request-scope variable in value binding expressions in order to specify column-specific attribute values. The name of this request-scope variable should be specified in the var attribute of the <o:columns> tag. In some cases it is more convenient to use column index instead of column data value when specifying values that should depend upon the column in which they are used. For this purpose, you can use an additional column index variable, whose name can be specified in the indexVar attribute of <o:columns> tag. This variable and the column data variable can be used to identify the currently displayed column.

Similarly to the ordinary columns, the content displayed in dynamic columns is specified by the set of child components located in the <o:columns> tag. The difference from the ordinary columns here is that with <o:column> tag, you have to use only the variable(s) identifying the currently displayed row, and in case of <o:columns> tag, you have to use variable(s) that identify the currently displayed column as well. The combination of these row- and column- identifying variables gives you the information on which cell is currently being displayed.

The <o:columns> tag does not have the id or rendered attributes. However, you can specify the identifier and a flag that indicates whether or not a column is visible for each dynamic column using the columnId and columnRendered attributes of the <o:columns> tag, respectively. These attributes should be specified as value-binding expressions that refer to identifier or a flag indicating whether column is visible for each dynamic column. You can use a column data variable specified in the var attribute in the expression for these attributes. Please note that column identifiers evaluated for columns inside the <o:columns> tag are used in the same way as id attributes of ordinary <o:column> tags, so the identifiers evaluated using this expression should be unique in bounds of the containing TreeTable.

The following example demonstrates the usage of the <o:columns> tag:

<o:treeTable var="node">
<o:dynamicTreeStructure nodeChildren="#{TreeTableBean.nodeChildren}"/>
<o:treeColumn>
    <f:facet name="header">
        <h:outputText value="name"/>
    </f:facet>
    <h:outputText value="#{node.name}"/>
</o:treeColumn>
<o:columns value="#{TreeTableBean.columnDatas}"
           var="col"
           indexVar="colIndex">
    <f:facet name="header">
        <h:outputText value="#{col.name}"/>
    </f:facet>
    <h:outputText value="#{node.columnValues[colIndex]}"/>
</o:columns>
</o:treeTable>

Similarly to an ordinary <o:column> tag, the <o:columns> tag supports sorting, filtering, style customization and columns-specific events.

Combining Columns into Groups

It is possible to combine columns into groups to reflect their logical connections. This can be done by enclosing several column tags into the <o:columnGroup> tag. This tag has the set of features similar to that of ordinary columns:

  • Specifying the "header" and "footer" facets for a group of columns. This will show an additional header (or footer) that spans across all of the inner columns.
  • Specifying style for a group of columns as described in the Column Styles section.
  • Specifying events for a group of columns as described in the Specifying User Events section.

Here's a simple example of using column groups:

<o:treeTable value="#{TreeTableBean.folders}" var="folder">
  <o:treeColumn>
    <f:facet name="header">
        <h:outputText value="Name"/>
    </f:facet>
    <h:outputText value="#{folder.name}"/>
  </o:treeColumn>
  <o:column>
    <f:facet name="header">
        <h:outputText value="Date created"/>
    </f:facet>
    <h:outputText value="#{folder.creationDate}"/>
  </o:column>
  <o:columnGroup>
    <f:facet name="header">
        <h:outputText value="Attributes"/>
    </f:facet>
    <o:column>
        <f:facet name="header">
            <h:outputText value="Read-only"/>
        </f:facet>
        <h:outputText value="#{product.attributes.readOnly}"/>
    </o:column>
    <o:column>
        <f:facet name="header">
            <h:outputText value="Hidden"/>
        </f:facet>
        <h:outputText value="#{product.attributes.hidden}"/>
    </o:column>
  </o:columnGroup>
</o:treeTable>

Note that there are both the columns those are enclosed into <o:columnGroup> tag and the columns those are not part of any group. It is also possible to create nested column groups, thus establishing an arbitrary hierarchy of columns.

It is possible to emphasize separation of columns into groups with a feature of customizing gridlines for different levels of columns (or groups). See the Column Group Separators section for details.

Changing Column Order

The columnsOrder attribute of the <o:treeTable> tag lets you explicitly specify the order in which the columns will be displayed. This attribute should be declared as a value-binding expression and the bound value should be a list containing column IDs for each column in the order you want them to appear. If the columnsOrder attribute is not specified, all columns are rendered in the order they are defined. Otherwise, only the columns whose IDs are included into this list are rendered.

In the example below, the columns in the TreeTable component are ordered explicitly.

<o:treeTable var="message"
              columnsOrder="#{Messages.columnsOrder}">
  <o:dynamicTreeStructure nodeChildren="#{Messages.nodeChildren}" />
  <o:treeColumn id = "subjectColumn"> ... </o:treeColumn>
  <o:column id = "authorColumn"> ... </o:column>
  <o:column id = "sentColumn"> ... </o:column>
  <o:column id = "sizeColumn"> ... </o:column>
</o:treeTable>

Drag & Drop Column Reordering

It is possible to let the user reorder columns interactively with drag & drop by adding the <o:columnReordering> tag into the <o:treeTable> tag. When this feature is turned on, the user can drag the column by its header and drop it into the appropriate place in-between columns. The current drop target is highlighted for user's convenience. In case of ??TreeTable??s with horizontal scrolling enabled (see the Content Scrolling section), the autoscroll areas will pop up on the header's left and/or right sides allowing the user to scroll the table while dragging the column.

The order of columns is read from and saved to the columnsOrder attribute of <o:treeTable> tag, so you can bind this attribute to your backing bean if you'd like to receive the column order changes. See the Changing Column Order section for the description of columnsOrder attribute.

Mere adding of the <o:columnReordering> tag will turn on the reordering behavior though you can also configure the attributes of this tag to adjust styles and appearance of various parts of UI that participate in the reordering process.

Dragging the column header creates a visual copy of the header cell that the user is dragging, and it's possible to apply an additional style to the dragged cell using the draggedCellStyle and draggedCellClass attributes. By default, the dragged cell is displayed as semitransparent and the transparency level can be configured using the draggedCellTransparency attribute, where 0.0 corresponds to the fully-opaque display, and 1.0 corresponds to the fully-transparent display.

The appearance of drop target can be customized with the following attributes

Attribute Description
dropTargetStyle, dropTargetClass The CSS class applied to the drop target area. The usual attributes that should be configured for drop target style are the "background" and "width" CSS attributes.
dropTargetTopImageUrl, dropTargetBottomImageUrl Allow customizing images that are displayed above and below the drop target (the default images display the arrows).

Finally, the appearance of the auto-scroll areas that appear on the horizontally-scrollable tables can be configured with the following attributes:

Attribute Description
autoScrollAreaStyle, autoScrollAreaClass The style for the autoscroll areas. You will usually want to configure the background, width and possibly border CSS attributes.
autoScrollAreaTransparency The transparency level for the autoscroll areas. The default value is 0.5, which means a semitransparent display. The value of 0.0 corresponds to the fully opaque display
autoScrollLeftImageUrl, autoScrollRightImageUrl The images that are displayed in the left and right autoscrolling areas respectively

Here's an example of turning on the column reordering feature for TreeTable with customizing the drop target color and binding the column order to a backing bean:

<o:treeTable ...
    columnsOrder="#{Messages.columnsOrder}">

<o:columnReordering dropTargetStyle="background: red"/> ... </o:treeTable>

Column Resizing

It is possible to let the user resize columns by adding the <o:columnResizing> tag as a child of <o:treeTable> tag. When column resizing is turned on, the user can drag the column header separators to resize columns. The total TreeTable width is not affected by the process of resizing columns. It should also be noted that if a TreeTable doesn't have a fixed width specification, for example when it is declared to have 100% width, then table layout behavior is slightly changed when column resizing is turned on. The TreeTable is loaded with its width properly calculated using the specified relative width, though after the page is loaded the TreeTable's width is fixed and is not recalculated.

The <o:columnResizing> tag can be added without specifying any attributes, though there are some optional configuration attributes. The resizeHandleWidth attribute specifies the size of the "dragging area" near the column header separator. This area can be wider than the separator itself to make it easier for the user to locate the draggable area. The minColWidth attribute can be used to specify the minimum width that a column can take after resizing. Both of these attributes can be specified in any CSS units except percent.

Here's an example of adding the column resizing capability to a TreeTable:

<o:treeTable var="message"
              columnsOrder="#{Messages.columnsOrder}"
              width="100%">
  <o:columnResizing resizeHandleWidth="10px" minColWidth="50px"/>

<o:dynamicTreeStructure nodeChildren="#{Messages.nodeChildren}" /> <o:treeColumn id = "subjectColumn"> ... </o:treeColumn> <o:column id = "authorColumn"> ... </o:column> ... </o:treeTable>

The TreeTable's width attribute must be specified when using the column resizing feature.

There are also two per-column attributes that are applicable only when TreeTable has the column resizing feature. It is possible to make certain column non-resizeable by assigning "false" to the column's resizeable attribute. There is also the possibility to specify the minimum resizing width on a per-column basis. Specifying the column's minResizingWidth attribute overrides the default minimum width value defined by the <o:columnResizing> tag.

Column width changes made by the user can be persisted between different visits of the appropriate page using the <o:columnResizing> tag's resizingState attribute. This attribute can be bound to a backing bean property having the org.openfaces.component.table.ColumnResizingState type. This property will be written to save the current column widths when columns are resized, and will be read when the table is rendered next time. The additional <o:autoSaveState> attribute defines when the resizing state is sent to the server (and thus when the resizingState attribute binding is updated). By default it is set to true, which means that column widths are saved on-the-fly with Ajax requests after any column is resized. Setting this attribute to false will turn off the column width saving Ajax requests and will make the column widths data to be sent to the server along with the nearest form submission (or Ajax TreeTable component submission).

Displaying Column Menus

It is possible to add the column menu to allow performing the standard column operations such as sorting, showing and hiding columns, or to provide custom column-specific operations. The column menu feature is turned on by specifying the "columnMenu" facet. Specifying this facet makes a drop-down button to appear in the column's header when the user hovers over the header, and pressing this button shows the menu. You can either specify the standard column menu with the <o:columnMenu> tag in this facet, or a custom menu with the <o:popupMenu> facet. By default, this menu will be available through the header of all columns except selection and check-box columns. You can turn off the displaying of column menu for a certain column(s), or turn it on for selection/check-box columns using the menuAllowed boolean attribute on <o:column> or other column tags.

It is possible to customize the content and appearance of the standard menu by customizing the <o:columnMenu> tag's attributes and child tags. Adding any menu item tags inside of the <o:columnMenu> tag will replace the standard structure with the custom menu item hierarchy. This provides the full flexibility for reordering, restyling or removing the standard items and adding the custom ones. The standard menu items can be specified with the following tags:

  • sortAscendingMenuItem tag as the name says allows sorting the column in an ascending order;
  • sortDescendingMenuItem tag allows sorting the column in an descending order;
  • hideColumnMenuItem allows hiding the column;
  • columnVisibilityMenu tag can be embedded into the ordinary <o:menuItem> tag to display the column visibility customization sub-menu, where all columns are listed with check-boxes against each of them.

Additionally you can place a <o:menuSeparator> tag to insert separators and a <o:menuItem> tag to add custom menu items. Similarly, you can avoid displaying the standard menu at all, and specify the popupMenu tag as the content of the "columnMenu" facet for an entirely custom column menu.

Here's a simple example of displaying the customized menu, with two additional "Select Column" and "Unselect Column" menu items:

  <o:treeTable id="treeTable" ...>
    ...
    <f:facet name="columnMenu">
      <o:columnMenu indentStyle="color: yellow">
        <o:sortAscendingMenuItem/>
        <o:sortDescendingMenuItem/>
        <o:hideColumnMenuItem/>
        <o:menuSeparator/>
        <o:menuItem value="Columns">
          <o:columnVisibilityMenu/>
        </o:menuItem>
        <o:menuSeparator/>
        <o:menuItem value="Select Column" onclick="selectColumn(O$('form:treeTable').getCurrentColumn().index);"/>
        <o:menuItem value="Unselect Column" onclick="unselectColumn(O$('form:treeTable').getCurrentColumn().index);"/>
      </o:columnMenu>
    </f:facet>
    ...
  </o:treeTable>

Note that in order to implement functionality for custom menu items, you can use the getCurrentColumn() client-side method to detect the column for which the popup menu is invoked. This function returns the client-side column object where only one field is currently available: index. This is a zero-based index of a column in a list of currently rendered columns.

The standard menu and menu item tags can be customized with the same attributes as the usual popupMenu and <o:menuItem> tags (except some obvious non-applicable attributes such as subMenuImageUrl for sortAscendingMenuItem since it can't have a sub-menu, etc).

The column visibility sub-menu (displayed as part of the standard menu or specified in a customized menu with the columnVisibilityMenu) has a two-fold way of detecting the column names for displaying in the menu. First, it checks the optional column's header attribute (which exists in all column tags), and if this attribute is not defined, then it inspects the content of the "header" facet of the appropriate column and takes the value of the first UIOutput component found in that facet (such as <h:outputText>).

The appearance of the drop-down button that appears in the column header and invokes the column's popup menu can be customized with the "columnMenuButton" facet. This facet must contain the <o:captionButton> tag where you can customize all appearance properties for the menu invoker button.

Note that the column visibility changes made with the column menu are reflected into the columnsOrder attribute of the <o:treeTable> tag, so you can bind that attribute to be able to save column visibility between different page visits.

Fetching Data on TreeTable Rendering

When the TreeTable component is rendered the data is fetched two times from the data source, the same as for the standard <h:dataTable> component. However, on the post requests, the data is fetched only once for the display-only TreeTables. The display-only mode means that there is no UIInput, UICommand components and the checkbox column and selection features are disabled. If the TreeTable is not in display-only mode, the data is fetched twice just like in the standard DataTable component.

Concurrent Data Modifications

The TreeTable component allows you to embed any editable components in its cells, for example HTMLInputText, HTMLSelectManyCheckBox, HTMLSelectOneListBox, etc. However, in this case, a problem with concurrent data modification may arise. For example, while one user is editing some nodes, the other can delete one of these nodes. The TreeTable component provides a mechanism for resolving this kind of problems. If node data meets the node objects requirements, edited data is saved properly, even if the node order has changed.

Inspecting the Displayed Rows

There are several factors that affect the list of items displayed in the table, such as filtering, sorting and node preloading strategies. You can get the list of data objects for the currently displayed rows in two ways:

  • Declare the displayedRowDatas attribute in your <o:treeTable> tag as a value binding that refers to a property of a list, set or array type. Note that the specified property will never be read by the TreeTable, and will only be written to.
  • Use the getDisplayedrowDatas() object of TreeTable class if you'd like to use a programmatic approach.

Note that the lists received in this way will include rows for all preloaded nodes, regardless of whether they are expanded or not.

Headers and Footers

The TreeTable component has the header and footer areas that are displayed as the first and the last rows of the table and span the width of the component. The contents of the areas can be specified with the "header" and "footer" facets of the <o:treeTable> tag. The styles for the areas can also be customized (see the section Section Styles).

The TreeTable component also has two special areas that are located right before and after the table. The contents of these areas can be specified with the "above" and "below" facets of the <o:treeTable> tag.

Note that the content of all the facets described above is refreshed after Ajax requests that reload the entire TreeTable content (as in the case of filtering and sorting updates).

<o:treeTable var="message" style="border:dotted 1px gray">
...
      <f:facet name="above">
        <h:outputText value="'Above' facet goes before the TreeTable"/>
      </f:facet>
      <f:facet name="header">
        <h:outputText value="'Header' facet goes as the first row of the TreeTable"/>
      </f:facet>
      <f:facet name="footer">
        <h:outputText value="'Footer' facet goes as the last row of the TreeTable"/>
      </f:facet>
      <f:facet name="below">
        <h:outputText value="'Below' facet goes after the TreeTable"/>
      </f:facet></o:treeTable>

The following figure shows all the facets defined in the previous example:

Empty Data Message

If there are no records to display in the cells of the TreeTable component, a default "No records" message is displayed. To turn it off, set the noDataMessageAllowed attribute to "false" (by default, it is "true"). You can specify your own message text by using the noDataMessage facet of the <o:treeTable> tag. To apply styles to the row displaying this message, use the noDataRowStyle and noDataRowClass attributes of the <o:treeTable> tag.

If there is data in the data source but no records satisfy the current filtering settings (see the section Filtering below), then a different message "No records satisfying the filtering criteria" is displayed. You can change this message text by using the noFilterDataMessage facet.

The example below shows a customized message for empty data in the TreeTable component.

<o:treeTable var="message"
       noDataRowStyle="color:red; font-weight:bold; font-size:20pt">
  <f:facet name="noDataMessage">
       <h:outputText value="There is no data to display">
  </f:facet>
...
</o:treeTable>

Content Scrolling

It is possible to configure the TreeTable component to scroll its content when all rows (and/or columns) cannot fit within the allotted area. This can be done simply by placing the <o:scrolling> inside of the <o:treeTable> tag. Adding this attribute makes the TreeTable to show the vertical scrollbar allowing the user to scroll through the TreeTable's data rows. Header and footer rows remain fixed independent of scrolling.

The <o:scrolling> tag makes it possible to turn on vertical or horizontal scrolling modes, or allow both scrolling directions at the same time. This can be done using the vertical and horizontal attributes of the <o:scrolling> tag, which are equal to true and false by default respectively. By default, assigning true to any of these attributes makes the appropriate scroll-bar to be displayed regardless of where all data (rows or columns) entirely fits in the visible area or not. You can set the autoScrollbars attribute to true to show the scrollbars only when there's something to scroll, so that they are automatically hidden when the data entirely fits in the visible area.

If vertical scrolling is turned on, the table's height is fixed according to the CSS height attribute specified for the table (through table's style or styleClass attributes). It is also possible to modify this behavior by setting the minimizeHeight attribute of <o:scrolling> tag to true. Setting this attribute will make the table reduce its height by removing the empty space that remains when there's little rows and no scrolling is required.

It is possible to exclude one or more columns from horizontal scrolling and fix them on the TreeTable's left or right side by specifying the fixed attribute of the appropriate column(s) or column group(s). Note that only the first (and/or last) column(s) are allowed to be fixed, which means that you can't declare the fixed attribute for a column that resides in the middle of column list and is surrounded by non-fixed columns.

The following example outlines the declaration of a TreeTable with both horizontal and vertical scrolling having its first two columns fixed:

<o:treeTable ...>
  <o:scrolling horizontal="true"/>
  ...

<o:checkboxColumn fixed="true" .../> <o:column fixed="true" .../> <o:column .../> <o:column .../> ... </o:treeTable>

The current scroll position can be detected and manipulated using the position property of the <o:scrolling> tag. This attribute should be bound to a variable of type java.awt.Point.

Sorting

The TreeTable component supports column-wise sorting. The user should click the header of any sortable column to sort the data displayed in it. Subsequent clicks on the header changes the sort order from ascending to descending, and vice versa.

Data can be sorted only by "sorting-aware" columns. To make a specific column sortable, you should specify the sortingExpression and, optionally, sortingComparator attribute for that column. The sortingExpression attribute specifies the value that should be used when sorting the rows by that column. It should be declared as a value-binding expression. The sortingComparator attribute defines the comparator that is used to compare the values provided by the sortingExpression attribute. This attribute should be specified as a value-binding expression and should reference the object that implements the java.util.Comparator interface. If the sortingComparator attribute is not specified, sortingExpression should evaluate to either a primitive type or an object that implements the java.lang.Comparable interface, for example String. To perform case-insensitive comparison of String values, the sortingComparator attribute provides a special "caseInsensitiveText" value.

The following example shows the TreeTable component in which messages appear sorted by subject on page load:

<o:treeTable var="message" sortLevel="0">
  <o:dynamicTreeStructure nodeChildren="#{Messages.nodeChildren}" />
  <o:treeColumn id="subjectColumn"
                sortingExpression="#{message.subject}">
    <f:facet name="header">
      <h:outputText value="Subject"/>
    </f:facet>
    <h:outputText value="#{message.subject}"/>
  </o:treeColumn>
  <o:column id="authorColumn">
    <f:facet name="header">
      <h:outputText value="From"/>
    </f:facet>
    <h:outputText value="#{message.author.userName}"/>
  </o:column>
</o:treeTable>

Dynamic columns support sorting as well. Just like ordinary columns, dynamic columns can be made sortable by specifying the sortingEnabled attribute in <o:columns> tag. In this case, all dynamic columns become sortable. Though in some cases it's needed to make only a portion of columns sortable. This can be accomplished by declaring the sortingEnabled attribute of the <o:columns> tag. This attribute can be specified as a value-binding expression that refers to a boolean value indicating whether or not the current dynamic column is sortable based on the column data variable. You can also optionally specify the sortingComparator attribute. Note that the purpose and usage of sortingEnabled and sortingComparator attributes are the same as for the <o:column> tag, but they must be specified as a value-binding expressions that include a column data variable for specifying different sorting values and different sorting comparators for each column.

Here is an example of using the sorting feature in dynamic columns:

<o:treeTable var="node">
  <o:dynamicTreeStructure nodeChildren="#{TreeTableBean.nodeChildren}"/>
  <o:treeColumn>
    <f:facet name="header">
        <h:outputText value="name"/>
    </f:facet>
    <h:outputText value="#{node.name}"/>
  </o:treeColumn>
  <o:columns value="#{TreeTableBean.dynamicColumns}"
           var="col"
           sortingExpression="#{node.dynamicColumns[col]}">
    <f:facet name="header">
        <h:outputText value="#{col}"/>
    </f:facet>
    <h:inputText value="#{node.dynamicColumns[col]}"/>
  </o:columns>
</o:treeTable>

It is also possible to make the selection and check-box columns sortable. This can be done simply by setting their sortable attribute to "true". Here's an example:

<o:treeTable value="#{tableBean.tableValue}"
             var="row">
  <o:multipleNodeSelection/>
  <o:selectionColumn sortable="true"/>
  <o:checkBoxColumn sortable="true"/>
  ...
</o:treeTable>

When the TreeTable component is loaded for the first time, its data is rendered unsorted. You can specify which column will be sorted on page load and in what order using the sortColumnId and sortAscending attributes. The sortColumnId attribute is a string attribute, where you specify the ID of the column by which to sort the table. The sortAscending boolean attribute is used to specify the sort order. When sortAscending is "true", the table is sorted in ascending order, and vice versa.

Because the TreeTable component displays hierarchical data, sorting can be performed only across a certain level of the hierarchy, i.e. by comparing the nodes only with their siblings. So sorting in the TreeTable component is performed among children of each separate node, without mixing with nodes of different parents.

The level at which to perform sorting is specified by the sortLevel integer attribute of the <o:treeTable> tag. The default value is -1, which means that sorting is applied to all levels of the hierarchy in the TreeTable component. When set to "0" (top-most level) or greater, sorting is restricted to only one specified level. For example, a value "0" means that only the nodes at the top-most level are sorted against each other, while all their children remain unsorted. A value "1" means that only the nodes of the level next to the top-most one are sorted, while all other levels are not affected.

The image that displays the sort direction is customizable. To change it, use the sortedAscendingImageUrl and sortedDescendingImageUrl attributes. Note that in order to have the column header text and sort image correctly aligned, the sort image should be approximately of the same height as characters in the header.

Sorting-Related Styles

It is possible to highlight headers of sortable columns using the following styling attributes:

Description
   Style attributes     
   Class attributes     
Sortable column header sortableHeaderStyle sortableHeaderClass
Rollover style for sortable column header sortableHeaderRolloverStyle sortableHeaderRolloverClass

The styles different parts of a sorted column can be customized using the following attributes:

Parts of a sorted column
    Style attributes     
    Class attributes     
Entire column sortedColumnStyle sortedColumnClass
Column header sortedColumnHeaderStyle sortedColumnHeaderClass
Column body sortedColumnBodyStyle sortedColumnBodyClass
Column footer sortedColumnFooterStyle sortedColumnFooterClass

Filtering

The TreeTable component provides a powerful mechanism for interactive data filtering to make it easier for the users to browse data sets of any size and complexity. It is possible to:

  • define column data filters,
  • define filters that search data on a complex expression rather than a single-column expression,
  • use different types of filter components,
  • place filter components inside of the table or anywhere on the page,
  • customize all aspects of filtering behavior including search condition, case sensitivity, etc.,
  • customize all aspects of filters' visual appearance,
  • use the composite filter builder (the CompositeFilter component) as a universal filter component to allow the user build complex filter criteria interactively.
  • eaily add support for handling large data sets while utilizing all kinds of filters attached to the table.
Basic Usage

Even though it has a lot of features and customization possibilities, filtering is quite easy to incroporate into a table. The filtering functionality is
defined using the filter tags, which when attached to a table, add a filtering interface and behavior according to the tag's customization. There are the following filter tags:

  • <o:inputTextFilter> – displays a text field that filters the data according to the expression specified in the filter.
  • <o:dropDownFieldFilter> – displays a drop-down field that filters the data according to the expression specified in the filter. The drop-down list contains all values that present in a table for the filter's expression or a custom list, so the user can type a value manually or select one from the list.
  • <o:comboBoxFilter> – displays a combobox that filters the data according to the expression specified in the filter. The combobox contains all values that present in a table for the filter's expression, or a custom list.
  • <o:compositeFilter> – displays a filter builder component where the user can compose a set of criteria based on table's columns. See the Using Composite Filter section below and the CompositeFilter component documentation.

These filters can be added in two ways:

  • Declared anywhere on a page and bound to the table using the filter's for attribute, which is used in the same way as the for attribute for the standard <h:outputLabel> and <h:message> components.
  • Placed into a "subHeader" (or other) facet of a table's column, which will automatically bind the filter to a containing table without using the for attribute (not applicable for <o:compositeFilter>).

Here's a simple example of specifying both an out-of-table filter and column filters:

<o:inputTextFilter for="tasksTree" expression="#{task.name}"/>
...
<o:treeTable id="tasksTree" var="task" ...>
  <o:dynamicTreeStructure .../>
  <o:treeColumn ...>
    <f:facet name="subHeader">
      <o:inputTextFilter/>
    </f:facet>
    <h:inputText value="#{task.name}"
  </o:treeColumn>
  <o:column ...>
    <f:facet name="subHeader">
      <o:dropDownFieldFilter/>
    </f:facet>
    <h:outputText value="#{task.owner}"/>
  </o:column>
  <o:column ...>
    <f:facet name="subHeader">
      <o:comboBoxFilter/>
    </f:facet>
    <h:outputText value="#{task.priority}"/>
  </o:column>
  ...
</o:treeTable>

The expression attribute defines a value that will be searched for (or filtered) with this filter. As you can see in the example above this attribute can be omitted when filter tag is declared inside of column. In this case the filter will automatically detect the expression from the first output component (UIOutput descendant) displayed by the column. Though you can specify the expression attribute explicitly if it should differ from the autodetected one, or if there's no output component in a column.

Using Composite Filter

As opposed to the simple one-field filters like those defined with <o:inputTextFilter>, <o:dropDownFieldFilter>, and <o:comboBoxFilter> tags, the composite filter (defined with <o:compositeFilter> tag) is a complex type of filter where the user interactively builds search criteria for searching across one or more columns.

Just like the simple filters, composite filter can be placed anywhere on a page and bound to a table with the for attribute, as demonstrated in this example:

<o:compositeFilter for="employeesTable"/>
...
<o:treeTable id="employeesTable" var="employee" ...>
  <o:dynamicTreeStructure .../>
  <o:treeColumn ...>
    <h:outputText value="#{task.owner}"/>
  </o:treeColumn>
  <o:column ...>
    <h:outputText value="#{employee.priority}"/>
  </o:column>
  ...
</o:treeTable>

This simple declaration attaches the composite filter to a table and makes it autodetect the set of columns, with their types and names from the attached table. Though you can turn off the autodetection functionality and specify the column data for this filter explicitly if the list of columns in this filter should be different than the autodetected one. See CompositeFilter documentation for details.

A composite filter doesn't conflict with the other filters attached to the same table, so you can for example optionally declare column filters as well, and the table will display the data that takes into account all of the attached filters.

The CompositeFilter component can also be used as a standalone filter where the user-composed filter criteria can be used by the application code without explicit attachment to a table. Please read the full information about using the composite filter on the CompositeFilter documentation page, and the sections below cover the details of using the simple filters.

Customizing Filtering Options

The <o:inputTextFilter>, <o:dropDownFieldFilter>, and <o:comboBoxFilter> filters can filter any type of data (through the expression attribute or the autodetected column expression). The converter for this type of data is detected by the filter automatically from the parent column or filter expression type (when expression is specified explicitly). It is also possible to specify the converter explicitly with the converter attribute or adding a a converter as a filter's child tag.

By default, the search is performed by substring if a filter is bound to a string type and by exact match for any other type of data. The exception is the <o:comboBoxFilter> filter which searches by exact match for all types of data by default. The default filtering condition can be changed using the condition attribute, which can take the following values:

  • "equals"
  • "contains" (applicable for only for String fields)
  • "beginsWith" (applicable for only for String fields)
  • "endsWith" (applicable for only for String fields)
  • "less"
  • "greater"
  • "lessOrEqual"
  • "greaterOrEqual"

It is also possible to invert the condition by prepending one of these values with not keyword. Here are examples:

<o:inputTextFilter condition="less" expression="#{product.price}" .../>
...
<o:dropDownFieldFilter condition="not contains" expression="#{product.features}" .../>

By default, the string values are compared in a case-insensitive way and this can be changed by specifying the caseSensitive attribute with a value of true.

The current filter value specified in the filter is reflected in the filter's value attribute, so you can bind this attribute to a backing bean if you'd like some default filtering values to be present when the page is shown, or to be able to save the user-specified values to a backing bean for processing or saving among page visits. The value attribute should be bound to a variable of type ExpressionFilterCriterion. An instance of this class holds the user-specified value in its arg1 property.

As mentioned above, <o:dropDownFieldFilter> and <o:comboBoxFilter> display a list of all values present in table records for the filter's expression. Though the automatically composed list can be replaced with the custom one using the options attribute that should return a collection of items of the same item type as values returned by the filter expression.

Customizing Filtering Behavior

The <o:dropDownFieldFilter> tag has the autosuggestion and autocompletion features turned on by default. Autosuggestion means automatically opening the drop-down list when the user starts typing, and filtering the options list based on the input. This behavior can be customized with the suggestionMode attribute, which accepts one of the following values:

  • "all" – the entire list of options will be shown regardless of input.
  • "stringStart" – only the items starting with the typed text will be shown.
  • "substring" – only the items containing the typed text will be shown.
  • "stringEnd" – only the items ending with the typed text will be shown.
  • "none" – no autosuggestion behavior takes place, which means that drop-down will not be automatically opened when the user starts typing in the filter field.
    The delay and minimal set of typed characters when the drop-down is autoopened can be customized with the suggestionDelay and suggestionMinChars attributes.
    Autocompletion is another related feature that completes the partially-specified value right in the field, and this behavior can be turned off by assigning false to the autoComplete attribute.

It is possible to restrict entering values in <o:dropdownFieldFilter> to a list of its options, which means that it won't be possible to enter a value that doesn't exist in its drop-down list, which makes the drop-down filter like combobox filter in functionality but with a different way of entering a value and different look. This can be turned on by specifying the customValueAllowed attribute with a value of false.

By default, the <o:inputTextFilter> and <o:dropDownFilter> filters have the autofiltering functionality turned on, which means that the table is automatically filtered as the user types the text in the field. The filtering is performed each time when the user stops typing in the field for a while. This autofiltering period can be changed with the autoFilterDelay attribute which should be specified as a milliseconds number. The autofiltering functionality can be turned off by specifying the autoFilterDelay attribute with a value of -1, which means that filtering will be performed when the user presses the Enter key or leaves the filtering field.

The <o:inputTextFilter> and <o:dropDownFieldFilter> filters can also be customized to have a limit on the number of typed characters with the maxlength attribute. By default it has a value of Integer.MIN_VALUE which means that there's no limit on the length of typed text.

Customizing Filter's Appearance

The drop-down and combobox filters display the following provide the following items for specifying special filtering conditions in addition to the filter value items:
In addition to the unique column values, the "comboBox" and "dropDownField" filter components provide three predefined filter values:

  • "<All> - displays all records, i.e. data is not filtered.
  • "<Empty> - displays only the records with empty values (only for combobox filters).
  • "<Non-empty> - displays all records with non-empty values (only for combobox filters).

The text for these items can be customized with the allRecordsText, emptyRecordsText, and nonEmptyRecordsText attributes respectively, and the style for these items can be customized with the predefinedCriterionStyle/predefinedCriterionClass attributes.

When using <o:inputTextFilter> and <o:dropDownFieldFilter>, you can specify the prompt text with the promptText attribute. The prompt text is a label or short instruction placed inside the filter field. The specified text will be shown to the user while the field is empty and disappear once it gets input focus. The style of prompt text can be customized with the the promptTextStyle and promptTextClass attributes.

All of the <o:inputTextFilter>, <o:dropDownFieldFilter>, and <o:comboBoxFilter> tags have the following common attributes:

Attribute Description
style/styleClass A style for the filter component.
rolloverStyle/rolloverClass A style for the filter component in rollover state (except <o:comboBoxFilter>).
focusedStyle/focusedClass A style for the filter component in rollover state (except <o:comboBoxFilter>).
tabindex, accesskey, title, dir,
lang
The standard attributes for input tags.

There are also many drop-down field specific attributes in the <o:dropDownFieldFilter> tag. These are attributes such as buttonAlignment, listAlignment, listStyle, listItemStyle, etc. They have the same meaning as their counterparts in the <o:dropDownField> tag. Please see the DropDownField documentation for the description of these attributes.

Filtering-Related Styles

You can apply a style to the sub-header row using the subHeaderRowStyle and subHeaderRowClass attributes. The subHeaderRowSeparator attribute lets you can create a style for a line that separates the sub-header row and the column header.

You should specify the subHeaderRowSeparator attribute in the same way as the CSS border property but without the prefix "border:". For example, subHeaderRowSeparator="1px dotted black".

Because the TreeTable component displays hierarchical data, the way it shows filtered nodes is different from how filtered rows are displayed in the DataTable. While the DataTable component displays only the rows that match filter criteria, the TreeTable component may display rows for the nodes that are not accepted by filter criteria. This happens when the TreeTable component needs to display a node at some deep level of the hierarchy which is accepted by filter criteria, whereas its parent nodes are not. In this case, all parent nodes of the accepted nodes are also displayed for the sake of keeping visible that part of the hierarchy that leads to the accepted node. By default, these "auxiliary" nodes are grayed out to distinguish them from filtered nodes.

You can customize the appearance of nodes that satisfy filter criteria by using the filterAcceptedRowStyle and filterAcceptedRowClass attributes. To define a style for the nodes that don't meet filter criteria but are needed to keep the hierarchy visible, use the filterSubsidiaryRowStyle and filterSubsidiaryRowClass attributes.

Node Selection

The selection feature lets the user select one or more nodes in the TreeTable component. Selection in the TreeTable is similar in usage to that in the DataTable component. The difference, however, is how single and multiple selection modes are configured in the TreeTable component (see the sections below). To learn more about the selection feature, please refer to the appropriate section in the DataTable documentation.

Single Selection Mode

To provide single node selection for the TreeTable component, use a child <o:singleNodeSelection> tag. To detect which node is currently selected or to change selection, the <o:singleNodeSelection> tag provides two value-binding attributes that can be bound to a backing bean:

  • nodeData - Defines the node data object for a currently selected node. A value of null means no node is currently selected. Note that if you want to change selection from the backing bean, the node data object provided by the nodeData attribute should be serializable and correctly implement the equals and hashCode methods.
  • nodePath - Defines the full path of a currently selected node. A value of null means no node is currently selected. This attribute should be bound to a property of the org.openfaces.component.table.TreePath type. Instances of the TreePath class are used to reference a node in the tree structure by its node value and node values of all its parent nodes.

If both attributes are specified, but refer to different nodes, the nodePath attribute takes precedence.

You can specify whether selection can be made with the mouse or keyboard (or both) by setting the mouseSupport or keyboardSupport attributes of the <o:singleNodeSelection> tag. Both attributes are "true" by default.

If you don't what to let the user change the selection, set the enabled attribute of the <o:singleNodeSelection> tag to "false" (by default, it is "true").

The following example shows configuration of single node selection with disabled keyboard support.

<o:treeTable var="message">
  <o:singleNodeSelection
          nodeData="#{Messages.selectedNodeData}"
          keyboardSupport="false"/>
  <o:dynamicTreeStructure
          nodeChildren="#{Messages.nodeChildren}" />
  <o:treeColumn>
    <f:facet name="header">
      <h:outputText value="Subject"/>
    </f:facet>
    <h:outputText value="#{message.subject}"/>
  </o:treeColumn>
</o:treeTable>

Note that when the user changes selection, a newly selected node is highlighted on the client side without any interaction with the server. So the properties bound to the nodeData and nodePath attributes are updated only when the form with the TreeTable component is submitted to the server. However, it is possible to execute a client action right on selection change. You can do it in two ways:

  • Using the onchange attribute of the <o:singleNodeSelection> tag. This is a client-side event attribute in which you should specify JavaScript code that should be executed every time the user changes selection.
  • Using the action attribute of the <o:singleNodeSelection> tag. The use of this attribute is similar to the action attribute of the HTMLCommandButton component. This attribute can either specify a string defining the static outcome of the selection change action, or it can be defined as a method-binding expression, so that you can execute any Java code on the server when the user changes selection. In any case, the action attribute causes the form submission on selection change.
  • You can also turn on the Ajax mode where the Ajax request will be automatically executed when the user changes selection. This can be done using the render attribute where you can specify the list of components that should be reloaded with Ajax when the selection is changed. This functionality is convenient for use cases when you need to update some components that depend on the currently selected item. The usage of the render attribute is the same as that for the <o:commandButton> tag. Note that when the render attribute is specified, the TreeTable and all its data including selection is submitted to the server for processing. If the action attribute is specified, the appropriate server-side action will also be executed during the Ajax request. By default, no components outside of the TreeTable are submitted and thus only TreeTable parameters themselves are available on the server during the Ajax request, though you can include additional components into the list of submitted components using the execute attribute. See the details on using the render and execute attributes in the CommandButton documentation.

To apply a style for a selected row, use the style and styleClass attributes of the <o:singleNodeSelection> tag. Note that these attributes are targeted at customizing the visual style according to the specified CSS declarations, but do not specify which HTML tags will be affected to achieve this. That is, these styles can technically be applied to different HTML tags depending on the browser or other conditions to ensure as uniform cross-browser appearance of the specified styles as possible. In most cases using these attributes is recommended.

There is also an additional rawStyleClass attribute which can be used if it is important to guarantee applying the specified CSS class(es) to the row tags themselves. In contrast with the style and styleClass attributes, this attribute might result in a browser-dependent display of styles, but it can be required if some other CSS declarations in your web design depend on a certain class name to be applied strictly to the row tags.

Note that, in general, it is not recommended to create a design that depends on the way that component's HTML is rendered. As a solution, the dedicated component's xxxStyle/xxxClass attributes should be used for styling different parts of components instead.
<p>The <cite>TreeTable</cite>'s rows in the current version are rendered with the usual HTML <tt>&lt;tr&gt;</tt>
    and <tt>&lt;td&gt;</tt> tags, and there is no intention to change it in the future currently, but it
    is possible that this will change at some point, so there's no guarantee that the
    <b>rawStyleClass</b> (and other "raw" classes) will be applied to the <tt>&lt;tr&gt;</tt> tags then.
</p></blockquote>
Multiple Selection Mode

To provide multiple selection for the TreeTable component, use a child <o:multipleNodeSelection> tag. The only difference between specifying single and multiple node selection is that the <o:multipleNodeSelection> tag has the nodeDatas and nodePaths attributes instead of the nodeData and nodePath attributes. These attributes must be specified as value-binding expressions that reference a list, set or array of node data objects and org.openfaces.component.table.TreePath instances, respectively. Empty lists mean an empty selection. Note that if you want to change selection from the backing bean, the node data objects provided by the nodeDatas attribute should be serializable and correctly implement the equals and hashCode methods.

All other features, including selection change notifications and styles, are configured in the same way as for single node selection.

The following example shows the TreeTable component in multiple node selection mode.

<o:treeTable var="message">
  <o:multipleNodeSelection
          nodeDatas="#{Messages.selectedNodeDatas}" />
  <o:dynamicTreeStructure
          nodeChildren="#{Messages.nodeChildren}" />
  <o:treeColumn header="Subject">
    <h:outputText value="#{message.subject}"/>
  </o:treeColumn>
</o:treeTable>
Hierarchical Selection Mode

This selection mode is similar to the multiple selection mode described in the previous section, but it includes the behavior where selection of child and parent nodes is interdependent. This selection mode works in conjunction with the selection column and/or SelectRowCheckbox component described below. When the user clicks a check-box for a node which has any child nodes, then selection for all of its child nodes is set (or unset) automatically depending on the state of the parent check-box. And the other way, if all of the child nodes are selected (or unselected), then the parent node is also automatically marked as selected (or unselected). If some child nodes are selected and some are not then the check-box for the parent node will be in the "undefined" state, as can be seen in tri-state check-boxes. Such a behavior can commonly be seen in various installation programs where the user can make a bulk selection of features by their categories, or customize contents of certain categories individually.

This behavior works with any depth of tree structure, but it works only on the nodes which are currently loaded on the client (see Expanding and Preloading Nodes). For example if the preloadedNodes attribute is set to all then then nodes in the entire tree structure are included into the auto-selection behavior described above, regardless of whether there are any collapsed nodes. But if only a part of nodes is preloaded to the client then this behavior will not include the nodes which have not been loaded yet.

Aside for the tag name, the usage of this tag is the same as for the multiple selection described above. Here's an example, which includes the select row checkbox (see the Using a Select Row Checkbox section below for more information):

<o:treeTable var="message">
  <o:hierarchicalNodeSelection
          nodeDatas="#{Messages.selectedNodeDatas}" />
  <o:dynamicTreeStructure
          nodeChildren="#{Messages.nodeChildren}" />
  <o:treeColumn>
    <f:facet name="header">
        <o:selectAllCheckbox/> Subject
    </f:facet>
    <o:selectAllCheckbox/> <h:outputText value="#{message.subject}"/>
  </o:treeColumn>
</o:treeTable>

The <o:selectAllCheckbox> tag in the column's header is optional, but you can use it to trigger selection for all nodes in the tree. You can also use the selection column instead of, or in addition to, the SelectRowCheckbox on such tree tables with hierarchical selection.

The API for the <o:hierarchicalNodeSelection> tag is the same as for the <o:multipleNodeSeelction> tag, but there's an additional trackLeafNodesOnly attribute (true by default). By default, when data for a TreeTable with hierarchical selection is submitted, nodeDatas and nodePaths attributes receive only the list of selected leaf nodes (nodes which don't have any parent nodes). This is appropriate for the cases when parent nodes serve just as convenient means of group selection, but it's of course still possible to select parent nodes in the user interface itself. Setting this attribute to false will also include all of the selected parent nodes along with the leaf ones. Note that the parent nodes with the "undefined" state are not included into the list of selected nodes here.

Keyboard navigation for a TreeTable having a hierarchical node selection is disabled, and it's only possible to control this kind of selection through selection column and SelectRowCheckbox components, which are described below. Similar to the other selection modes, the selected rows are highlighted by default. You can turn this behavior off by specifying the style="background: none" attribute of <o:hierarchicalNodeSelection> tag.

Using a Selection Column

The TreeTable component provides a special "selection column" that displays check boxes for multiple node selection or radio buttons for single node selection. The selection column is an alternative way for the user to change selection and see which row(s) is selected. The selection column is denoted by the <o:selectionColumn> tag.

For multiple selection mode, you can add a child <o:selectAllCheckbox> tag to the "header" or "footer" facets (or both) of the table and/or any of its columns. This will display a check box which when clicked will select/deselect all rows. Note that this affects only the nodes that are already preloaded to the client, e.g. it won't select/deselect a node if its parent node has never been expanded (and it wasn't preloaded explicitly using the preloadedNodes attribute).

Here's an example of a selection column that works on a TreeTable with multiple node selection.

<o:treeTable var="message">
  <o:multipleNodeSelection nodeDatas="#{Messages.selectedNodeDatas}" />
  <o:dynamicTreeStructure nodeChildren="#{Messages.nodeChildren}" />
  <o:selectionColumn>
    <f:facet name="header">
      <o:selectAllCheckbox />
    </f:facet>
  </o:selectionColumn>
  <o:treeColumn header="Subject">
    <h:outputText value="#{message.subject}"/>
  </o:treeColumn>
</o:treeTable>
Using a Select Row Checkbox

When using multiple selection, it's also possible to display the row selection check-box in any place of a row using the <o:selectRowCheckbox> tag. Check-boxes added in this way work in the same way as check-boxes displayed by the selection column, and you can use these features interchangeably depending on the design requirements of your application. You can actually use selection column and SelectRowCheckbox component at the same time if needed. The <o:selectRowCheckbox> tag can be placed in any place of any TreeTable's column similar to any other regular components displayed in TreeTable's columns.

The <o:selectRowCheckbox> tag has most the attributes of <o:selectBooleanCheckbox> tag, which allows customizing all of the check-box'es appearance aspects, such as an ability to display custom check-box images in different states. Please see the <o:selectRowCheckbox> tag reference for the list of all supported attributes.

Here's a simple example of placing the SelectRowCheckbox into a tree column near the column's text. Note that the SelectAllCheckbox can still be used here if needed, even without using a selection column.

<o:treeTable var="message">
  <o:multipleNodeSelection nodeDatas="#{Messages.selectedNodeDatas}" />
  <o:dynamicTreeStructure nodeChildren="#{Messages.nodeChildren}" />
  <o:treeColumn>
    <f:facet name="header">
      <h:panelGroup>
        <o:selectAllCheckbox /> <h:outputText value="Subject"/>
      </h:panelGroup>
    </f:facet>
    <o:selectRowCheckbox/> <h:outputText value="#{message.subject}"/>
  </o:treeColumn>
</o:treeTable>

Using a Checkbox Column

The TreeTable component provides a "checkbox column", which is a special visual component that is rendered as a column of check boxes and whose values are not stored in the node data object. You can use it as an alternative of or in addition to multiple selection or when you need to implement complicated selection models.

To add a checkbox column to the TreeTable component, use the <o:checkboxColumn> tag. It has two attributes, rowDatas and nodePaths which should be defined as value-binding expressions that reference a list of node data objects and org.openfaces.component.table.TreePath instances, respectively. Please note that the rowIndexes attribute is only applicable for the DataTable component. These attributes are mutually exclusive and you will normally use just one of them, which suits application logic more closely. In addition, you can add a child <o:selectAllCheckbox> tag to the "header" or "footer" facets (or both) of the <o:checkboxColumn> (this tag can also be used in the Selection Column component).

Note that the checkbox column imposes the same requirements on the data source as does the selection feature: node data should be serializable and correctly implement the equals and hashCode methods, or the nodeKey attribute should be provided.

It is also important to note that, while the selection column is just an alternative way to manage selection, the checkbox column stores a list of selected nodes independently of the selection and independently of each other (when several checkbox columns are used in the same TreeTable component). For example, you can have selection and two checkbox columns that can all be bound to their own properties.

It is also possible to optionally disable or hide check boxes for some nodes depending on application logic. This can be done using the disabled and visible attributes of <o:checkboxColumn> tag respectively. These attributes can be specified as a simple true/false value, or as an EL expression, which uses any of the row variables (see the Request-Scope Variables section).

The following example shows the usage of the checkbox column with some of the check boxes disabled depending on row data objects.

<o:treeTable var="mesasage">
  <o:checkboxColumn rowDatas="#{Messages.checkedMessages}" disabled="#{message.locked}">
    <f:facet name="header">
      <o:selectAllCheckbox />
    </f:facet>
  </o:checkboxColumn>
  ...
</o:treeTable>

Dynamic Data Loading

The TreeTable component supports dynamic data loading for such features as sorting, filtering, and node expansion, using Ajax. The useAjax boolean attribute specifies whether or not to use Ajax. By default, it is "true", which means Ajax is enabled.

If Ajax is not used, when the TreeTable component requires data update, the entire page is submitted and re-rendered completely with new data for the TreeTable. With Ajax, the page is submitted "behind the scenes" with only the TreeTable component being re-rendered. In case of node expansion, when Ajax is enabled only newly expanded nodes are loaded from the server.

Specifying the content of the "above" and "below" facets

The "above" and "below" facets are updated during any actions involving Ajax reload of the TreeTable component: sorting, filtering and reloading with Ajax component. The following rules are used for placing the components in the "above" and "below" facets:

  • If a component located in the "above" and "below" facet is expected to change as a result of an Ajax request, it should have the id attribute specified in order for this component to be re-rendered during an Ajax request. If there are many such components inside the same facet, you should wrap them into any other component or HTML tag that has the id.
  • If a certain component is changing its rendered attribute during an Ajax request, this component should be placed in some container-component (such as <h:panelGroup>) with the id attribute specified.

Note that TreeTable component is a naming container (implements the NamingContainer interface), which means that it introduces a separate naming scope for all of its child components and facets, and you shouldn't worry about the table's child/facet ids to clash with components outside of the table.

Here is an example:

<o:treeTable ...>
...
<f:facet name="below">
<h:panelGroup id="panelGroup">
  <h:outputText value="#{BackingBean.value1}"/>
  <h:outputText value="#{BackingBean.value2}"/>
</h:panelGroup>
</f:facet>
</o:treeTable>

Expanding and Preloading Nodes

Using of the foldingEnabled attribute of the <o:treeTable> tag allows you to specify whether the user can expand/collapse nodes in the TreeTable component. By default, it is "true".

By default, when the TreeTable component is loaded, all its nodes are collapsed. You can change this behavior by setting the expansionState attribute. You can specify the expansionState attribute right on the JSP page or as a value-binding expression that should be bound to the property of org.openfaces.component.table.ExpansionState type. The org.openfaces.component.table.ExpansionState is just an interface that has different implementations for different expansion states. The expansionState attribute can take one of the following values:

  • "allExpanded" or an instance of the org.openfaces.component.table.AllNodesExpanded class - All nodes are displayed in the expanded state.
  • "allCollapsed" or an instance of the org.openfaces.component.table.AllNodesCollapsed - All nodes are displayed in the collapsed state.
  • "levelsExpanded:NUMBER", where NUMBER is an integer number greater than or equal to zero. It specifies the number of node levels, starting from the top-most one, in which the nodes are displayed in the expanded state, while all nodes below this level are collapsed. For example, expansionState="levelsExpanded:1" means that only root nodes are expanded. A value of "0" means that no nodes are expanded. If the expansionState attribute is specified as a value-binding expression, it should be bound to an instance of the org.openfaces.component.table.SeveralLevelsExpanded class. The constructor of this class receives one integer parameter specifying the level up to which the nodes are expanded like described above.

In addition to these three values, which can be set both right on the JSP page and when using value binding, there's one more value which can be set only with value binding. Specifying the expansionState attribute as an instance of the teamev.jsf.component.treetable.DynamicNodeExpansionState class denotes all other expansion states of the TreeTable component which cannot be described with the above three types of values (for example, all nodes are collapsed except one). This class has two constructors: a no-args constructor and a constructor receiving an instance of org.openfaces.component.table.ExpansionState to serve as a default expansion state. While the previously described classes represent the "static" expansion state and it's not possible to specify an expansion state of individual nodes for them, DynamicNodeExpansionState has the setNodeExpanded(TreePath keyPath, boolean expanded) method which can be used to flexibly customize the expansion state on a per-node basis. If you need to expand some specific node programmatically in your application, you can use the expandNodePath(TreePath nodeKeyPath) method on TreeTable component's instance itself. This method invokes setNodeExpanded method to ensure that all of the parent nodes of the specified node are expanded. Note that both the DynamicNodeExpansionState.setNodeExpanded and TreeTable.expandNodePath methods receive an instance of TreePath, which consists of node key objects instead of node data objects. Note that node key objects are the same as node data objects if <o:dynamicTreeStructure> tag of this TreeTable doesn't contain the nodeKey attribute.

Although the TreeTable component can be configured to load with all nodes collapsed, you can specify that some of the collapsed nodes are preloaded to the client using the preloadedNodes attribute. This makes nodes expand faster. That is, when a collapsed node whose child nodes are preloaded is expanded by the user, these nodes will be shown immediately without any server request being sent. The preloadedNodes attribute can be specified right on the JSP page or as a value-binding expression that references the org.openfaces.component.table.PreloadedNodes class. Like the org.openfaces.component.table.ExpansionState class, it's just an interface that has different implementations. The preloadedNodes attribute can take one of the following values:

  • "none" or an instance of the org.openfaces.component.table.NoNodesPreloaded class - No children of collapsed nodes will be preloaded. This is a default value.
  • "all" or an instance of the org.openfaces.component.table.AllNodesPreloaded class - All children of collapsed nodes at all levels will be preloaded. So the entire TreeTable component can be browsed without any requests to the server.
  • "levelsPreloaded:NUMBER", where NUMBER is a positive integer number. It indicates the total number of node levels, starting from the top-most one, in which the nodes will be preloaded. For example, preloadedNodes="levelsPreloaded:2" means that only root nodes and their immediate children are preloaded. So if, for example, the TreeTable is loaded with all nodes collapsed, the root nodes can be expanded without requests to the server, and deeper levels will require a request to the server to load missing nodes. If the preloadedNodes attribute is specified as a value-binding expression, it should be bound to an instance of the org.openfaces.component.table.SeveralLevelsPreloaded class. The constructor of this class receives one integer parameter which specifies the number of preloaded node levels as described above.

There are two ways of sending a request to the server to load missing nodes. This depends on the value of the useAjax attribute (see the section Dynamic Data Loading ). By default, it is "true", which means that only nodes that need to be loaded are requested from the server. Otherwise, the entire page is reloaded along with expanded nodes.

Keyboard Navigation

The TreeTable component provides keyboard support for selecting and expanding/collapsing nodes. When single or multiple selection is enabled, a selected node can be changed with the keyboard. This feature is enabled by default, and, if necessary, you can disable it by setting the keyboardSupport boolean attribute of the <o:singleNodeSelection> or <o:multipleNodeSelection> tags to "false".

If selection is provided, and therefore, there's nothing to control from the keyboard, the TreeTable component is not focusable. However, if selection is configured in the TreeTable component and keyboard support is enabled, the TreeTable automatically becomes focusable. So you can either press the Tab key or click anywhere inside the TreeTable component to focus it.

You can customize the appearance for a focused TreeTable component by using the focusedStyle and focusedClass attributes.

The following keyboard shortcuts are available for node selection and expansion:

MS Windows/Linux Mac OS Action
Up Arrow Up Arrow Moves selection one row up from the current one.
Down Arrow Down Arrow Moves selection one row down from the current one.
Home Up-left arrow Selects the first currently visible row.
End Down-right arrow Selects the last currently visible row.
Shift+Up Arrow, Down Arrow, End, Home Shift+Up Arrow, Down Arrow, Up-left arrow, Down-right arrow Selects adjacent rows. Note that only contiguous row ranges can be selected with the keyboard.
Left Arrow/Minus Sign Left Arrow Collapses a currently selected node.
Right Arrow/Plus Sign Right Arrow Expands a currently selected node.

In addition, the user can select non-contiguous row ranges by pressing the Ctrl key and clicking rows with the mouse.

Just like for the standard focusable components you can specify the tabindex attribute for the <o:treeTable> tag to control the input focus order.

Customizing Individual Rows and Cells

In addition to an ability to customize all rows in the TreeTable's body at the same time, there is an ability to customize individual rows and cells based on displayed data or any other condition using the <o:row> and <o:cell> tags.

The <o:row> and <o:cell> tags are used to specify content, style or client-side events for specific rows and cells, respectively. In addition, you can merge several cells in a row using the <o:cell> tag (this feature is also known as a colspan feature).

To customize the individual rows, you should add the <o:row> tag as a child of the <o:treeTable> tag. There is a possibility to customize styles and client-side events for the rows that meet the criterion specified in the condition attribute of the <o:row> tag. The condition attribute should be specified as an expression that uses the request-scope variables those refer to the current row. The expression specified in the condition attribute should return a boolean value. The default value is true, which means that if the condition attribute is omitted then the appropriate attributes and child components of the <o:row> tag will be applied to all data rows.

The following example demonstrates making text in all root nodes green:

<o:treeTable var="message"
             nodeLevelVar="level">
  <o:row condition="#{level == 0}" style="color:green;"/>
  ...
</o:treeTable>

It is also possible to customize cells and their contents in the appropriate rows. This can be done by placing the <o:cell> tags as child tags for the Row component as described below.


The individual cells can be customized by adding the <o:cell> tags as children of the <o:row> tag. There are two ways of specifying <o:cell> tags within a row, which differs in a way how cell customizations are applied to columns within a row. The first one is creating a list of so called free cells (<o:cell> tags without columnIds or condition attributes), which results in customizing cells one-by-one starting from the first column. The second one is explicitly binding cells to some specific columns within the row using the columnIds or condition attributes of <o:cell> tags. The first approach (with a list of free cells) is most appropriate if you'd like to override declarations for all cells in a row, and the second one is good if you need to customize just one or a few cells, and retain the rest of the row's cells intact.

Regardless of the way that <o:cell> tags are bound to columns within a row, each <o:cell> tag has the following possibilities for cell customization. The style and styleClass attributes can be used to customize a style for the appropriate cells (see Conditional Styles section). There are also attributes for customizing cell's client-side events (see Specifying User Events section). The <o:cell> tags may have no content if you just need to customize cell's styles or events. But it is also possible to customize cell's contents that should be displayed instead of the default cell contents. This can be done by placing child components inside of <o:cell> tag. These components just like ordinary components inside of <o:column> tags can use the request-scope variables referring to the current row.

You can specify one or more of free cells, up to the number of columns declared in the table. Free cells are applied to the appropriate columns in the order that columns are declared on the page. The example below shows customizing the first two cells of each row that don't have children.

<o:treeTable var="message"
             nodeHasChildrenVar="nodeHasChildren">
  <o:row condition="#{nodeHasChildren == false}">
    <o:cell style="color:gray;"/>
    <o:cell style="color:silver;"/>
  </o:row>
  ...
  <o:column>...</o:column>
  <o:column>...</o:column>
  ...
</o:treeTable>

In addition, or as an alternative to specifying free cells, you can also specify any number of explicitly-bound cells. You can either use columnIds attribute, or condition attribute in <o:cell> tags to specify explicitly-bound cells. Note that unlike using free cells, using these attributes you can optionally make a single <o:cell> declaration to be applied to more than one column in the same row.

If you need to assign the Cell component to some specific column(s) you can do so by declaring the columnIds attribute of the <o:cell> tag. This attribute allows specifying identifiers of the columns in which the cells are to be customized. The column identifiers should be separated by a comma. You can also specify the columnIds attribute as a value-binding expression. In this case, you should bind this attribute to an array or a collection of java.lang.String class instances.

The following example demonstrates the Cell components assigned to the columns by identifiers:

<o:treeTable var="message"
             nodeLevelVar="nodeLevel">
  <o:row condition="#{nodeLevel > 0}">
    <o:cell columnIds="subjectColumn, fromColumn" style="text-align:left; color:green;"/>
  </o:row>
  ...
  <o:column id="subjectColumn">...</o:column>
  ...
  <o:column id="fromColumn">...</o:column>
  ...
</o:treeTable>

Another possibility to specify explicitly-bound cells is specifying a condition that defines columns in which the cells are to be customized. To do so you should use the condition attribute. This attribute should be specified as a value-binding expression that returns a boolean value based on the request-scope variables referring to the current cell. Returning true means that the <o:cell> tag will be applicable to a cell determined by the given set of request-scope variables.

Here is an example of assigning the cells to the columns using condition:

<o:treeTable var="message"
             nodeLevelVar="nodeLevel">
  <o:row condition="#{nodeLevel > 0}">
     <o:cell column="condition:#{columnIndex == 0}" style="text-align:left; color:green;"/>
  </o:row>
  ...
</o:treeTable>
Please note that the columnIds and condition attributes are mutually exclusive.

It is also possible to specify both free cells and explicitly-bound cells inside of the same <o:row> tag. Just place free cells first, and explicitly-bound ones afterwards. If several <o:cell> declarations will be applicable to the same displayed cell then the styles and events from all applicable cell declarations will be applied to the same displayed cell.

You can mix the <o:cell> tags with the columnIds or condition attributes and without these attributes specified within one row. In this case the cells without the columnIds or condition attributes are applied first regardless of the order of the tag declaration.

Support for Merging Row Cells

The OpenFaces TreeTable also provides an ability to merge several cells inside of a single row. To merge several cells within one row, you should specify the span attribute of the <o:cell> tag. The span is an integer attribute that is set to 1 by default. This attribute defines a number of cells to the right of this cell (including this cell itself) that should be merged with this cell, so a value of 1 means that no cells are "attached" to this one.

Note that the span attribute is just an additional possibility of the <o:cell> tag, and it can be used in combination with all other customization possibilities provied by this tag.

Below is an example with a table consisting of three columns. The cells in the second row are merged across all three columns and contain the custom content text displayed using the <h:outputText> component:

Below is an example with a TreeTable consisting of six columns. The cells in the root nodes are merged across all six columns:

<o:treeTable var="message"
             nodeLevelVar="nodeLevel">
  <o:row condition="#{nodeLevel == 0}">
     <o:cell span="6"/>
  </o:row>
  ...
</o:treeTable>

Please note that when the cells are merged, the content, styles and events from the first of the merged cells are used. Content, styles and events from the other merged cells are ignored.

Customizing Styles

Section Styles

By default, the TreeTable component uses a default style. To turn it off, set the applyDefaultStyle boolean attribute of the <o:treeTable> tag to "false".

Like the <o:dataTable> tag and HTML <table> tag, the <o:treeTable> tag supports the align, bgcolor, dir, rules, width, border, cellspacing, and cellpadding attributes. Also, the <o:column>, <o:selectionColumn> and <o:treeColumn> tags have the width, align and valign attributes that are rendered onto the <col> tag of the respective column.

The TreeTable component provides a number of style attributes for customizing its header, body, and footer sections.

     Part of TreeTable      
   Style attributes    
   Class attributes    
    Example legend    
Entire component style styleClass  
Entire component in the rollover state rolloverStyle rolloverClass  
TreeTable header headerSectionStyle headerSectionClass
TreeTable body bodySectionStyle bodySectionClass
TreeTable footer footerSectionStyle footerSectionClass

Note that the text-related part of the style and styleClass attributes (font, color, text-alignment, etc.) will not be applied correctly to all parts of the TreeTable component. To specify text styles, use the textStyle and textClass attributes instead of style and styleClass.

Row Styles

The TreeTable component allows you to define styles for the rows that span the header and footer of the component or its individual columns. All row style-related attributes of the <o:treeTable> tag are listed in the table below:

        Types of rows        
   Style attributes    
   Class attributes    
     Example legend      
Table header row commonHeaderRowStyle commonHeaderRowClass
Column header row headerRowStyle headerRowClass
Sub-header row subHeaderRowStyle subHeaderRowClass
Body rows bodyRowStyle bodyRowClass  
Body odd rows (if different from the body row style) bodyOddRowStyle bodyOddRowClass  
Body rows in the rollover state rolloverRowStyle rolloverRowClass  
Column footer row footerRowStyle footerRowClass
Table footer row commonFooterRowStyle commonFooterRowClass
NOTE that although row style attribute declarations, and other <cite>TreeTable</cite> styling
attributes, specify the way that appropriate parts of <cite>TreeTable</cite> component will look from
the user's standpoint, the developers shouldn't rely on how the appropriate CSS classes are applied to
the HTML tags generated by the <cite>TreeTable</cite> component, unless this is mentioned in
documentation explicitly.

<p>In particular you cannot rely on the fact that CSS classes specified with <b>bodyRowClass</b>
    attribute are applied to the <tt>&lt;tr&gt;</tt> tags of the generated HTML code, as they can for
    example be applied to the appropriate <tt>&lt;td&gt;</tt> tags, to make style declarations look as
    uniform as possible across different browsers, different rendering modes, etc.</p></blockquote>
Styles Example

The following example shows the styles applied to the sections of the TreeTable component and rows that span the column headers and footers:

<o:treeTable id="treeTable" var="message"
             expansionState="#{TreeTableBean.forumTreeTableExpansionState}"
             nodeLevelVar="level" width="40%"
             headerSectionStyle="font-size:13pt; color:#2e343d;"
             bodySectionStyle="background-color:#fef9ee; color:#106574"
             footerSectionStyle="font-size:13pt; color:#223957"
             headerRowStyle="background-color:#e1caa2"
             footerRowStyle="background-color:#aabede"
             commonHeaderRowStyle="background-color:#aec2c5"
             commonFooterRowStyle="background-color:#769ecb"
             subHeaderRowStyle="background-color:#faefd2">
  ...
</o:treeTable>

And here is the result:

Column Styles

A style can also be defined for a specific column of the TreeTable component. The style attributes listed below can be applied to all supported column tags:

Part of the column Style attributes Class attributes
Entire column style styleClass
Column header headerStyle headerClass
Column filter cell filterCellStyle filterCellClass
Column body bodyStyle bodyClass
Column footer footerStyle footerClass

The appearance of rows in the body section of the TreeTable component can be customized with the bodyRowStyle and bodyRowClass attributes of the <o:treeTable> tag. Additionally, you can use the bodyOddRowStyle and bodyOddRowClass attributes to define a style for odd rows. Creating alternate styles brings contrast between adjacent rows.

The <o:columns> tag also supports all above mentioned attributes. These attributes can be specified as value-binding expressions that use a column data variable specified in the var attribute of the <o:columns> tag.

In addition, all of the above attributes, except filterCellStyle and filterCellClass can be specified for the <o:columnGroup> tag. Header and footer style attributes are applied to the group's header and footer cells respectively, and general column style and column body styles are applied to the respective parts of each column inside of the group.

Other Styles

The TreeTable component supports styles related to the sorting and filtering features. They are described in the sections Sorting and Filtering. Additional styles are provided for the cell containing an expansion toggle button (see the toggle styles) and for the message displayed for empty data (see the section Empty Data Message).

Gridline Styles

You can specify styles for any type of separator lines within the TreeTable component. Each of them has its own attribute which should be used within the <o:treeTable> tag.

Type of separators
      Attribute      
Horizontal lines between body rows horizontalGridLines
Vertical lines between columns in the body area verticalGridLines
Table header bottom line commonHeaderSeparator
Table footer upper line commonFooterSeparator
Header bottom line headerHorizSeparator
A line that separates the column headers row and the sub-header row subHeaderRowSeparator
Footer upper line footerHorizSeparator
Vertical lines between column headers headerVertSeparator
Vertical lines between column footers footerVertSeparator

NOTE: You should specify all separator style attributes in the same way as the CSS border property but without the prefix "border:".

Note that if the TreeTable component has any gridlines or separators specified, the border, rules, and cellSpacing attributes of the <o:treeTable> tag take no effect.

The following example shows customized gridlines and separators in the TreeTable component:

<o:treeTable var="message"
             horizontalGridLines="1px dotted gray"
             verticalGridLines="1px dotted gray"
             commonHeaderSeparator="3px solid gray"
             commonFooterSeparator="3px solid gray"
             headerHorizSeparator="2px solid gray"
             subHeaderRowSeparator="1px dotted black"
             footerHorizSeparator="2px solid gray"
             headerVertSeparator="1px solid gray"
             footerVertSeparator="1px solid gray">
  <o:singleNodeSelection/>
  <o:dynamicTreeStructure nodeChildren="#{Message.nodeChildren}"/>
  <o:treeColumn>
    <f:facet name="header">
      <h:outputText value="Subject"/>
    </f:facet>
    <h:outputText value="#{message.subject}"/>
  </o:treeColumn>
</o:treeTable>

And here is the result:

Column Group Separators

The previous section describes the way that gridlines can be customized in a table without grouped columns, though there are some additional customization possibilities when a table contains column groups:

  • Specifying different styles for separators between ordinary columns and column groups. This can be done by specifying a list of comma-separated gridline styles in the verticalGridLines, headerVertSeparator and footerVertSeparator attributes, for example as follows: "1px solid silver, 2px solid silver". This will make the first style in the list to be used for ordinary column separators, and the second style in the list to be used for column group separators. Actually, the list of styles is not restricted to two items – you can specify any number of styles in this attribute, which can be required in case of deeper column hierarchies when there are groups that contain other column groups. The default value for the verticalGridLines attribute is "none, 1px solid #e0e0e0", which means that there are no separators between the ordinary columns, and there are light-grey separators between column groups.
  • Customizing horizontal separators between multiple header and footer rows that are created as a result of displaying several levels of columns and column groups. Similarly to customizing the vertical grid lines, this can be done by specifying one or more gridline styles in the multiHeaderSeparator and multiFooterSeparator attributes. The default value for these attributes is "none, 1px solid #a0a0a0", which means that there is no horizontal separator betwen first-level column group header and headers of its sub-columns, but if there is a more deep hierarchy of column groups then headers of the higher-level group headers will be separated with a gray line.
Conditional Styles

While all of the styles described above are applied to appropriate areas of the TreeTable component regardless of the data displayed in them, there is an ability to customize a style for individual rows or cells based on displayed data or any other condition using style and styleClass attributes of the <o:row> and <o:cell> tags, respectively. Specifying conditional styles are only a part of capabilities provided by these tags.

Here's an example of applying style to some individual rows and cells.

<o:treeTable var="item" nodeLevelVar="level" columnIndexVar="colIndex" ...>
  <o:row condition="#{item.important}" style="font-weight: bold"/>
  <o:row>
    <o:cell columnIds="itemColor" style="color: #{item.color}"/>
  <o:row>
  <o:row condition="#{level==1}">
    <o:cell condition="#{colIndex==2}" styleClass="cell5x2"/>
  <o:row>

<o:column id="itemColor">...</o:column> ... </o:treeTable>

Note that <o:cell> tags should be nested within the <o:row> tags. The three <o:row> declarations in this example introduce three rules for styling individual rows:

  • the first one emphasizes items having their "important" attribute equal to true with a bold text
  • the second declaration is applicable for all rows (there's no condition for that tag), and it specifies an individual color for all cells in the "itemColor" column, based on the value stored in each respective item.
  • the third declaration combines specifying condition for <o:row> and <o:cell> tags, which results in applying the specifying CSS class to the cells that meet both conditions.

Note that there are more scenarios of using the <o:row> and <o:cell> tags, for example it's possible to customize several cells within a single <o:row> declaration or customize cell content and events in addition to styling them. Refer to the Customizing Individual Rows and Cells section for the full information.

Style Hierarchy

Because of the variety of ways to style different parts of the TreeTable component, some style definitions may overlap. To avoid a style conflict, please keep in mind that cell styles have the highest priority, followed by row styles, column styles, section styles, and finally TreeTable styles having the lowest priority.

Since there are several styling attributes for most of the mentioned groups (row styles, column styles, etc.), each group defines its own list of in-group priorities (listed from higher to lower below):

  • Row styles: style for selection, rolloverRowStyle, conditional row styles, bodyOddRowStyle, bodyRowStyle
  • Column styles: headerStyle/bodyStyle/footerStyle, style
  • TreeTable styles: focusedStyle, rolloverStyle, style

Note that these in-group priorities are only applicable when styles are specified with *Style tags. Specifying the in-group priorities using the *Class tags are subject to the standard CSS cascading rules, which means that the order of CSS declarations is taken into account. The CSS classes declared later on a page take precedence over the ones declared earlier. This can be important for conflicting style declarations. For example let's consider a TreeTable whose bodyRowClass attribute and the styleClass attribute in the <o:singleNodeSelection> tag both have different "background-color" declarations in the respective classes. In order for selection to be visible in this case, the body row class declaration should go before the selection class declaration.

Specifying User Events

The TreeTable component supports a set of standard client-side events. You can specify them by using the following attributes of the <o:treeTable> tag: onclick, ondblclick, onmousedown, onmouseover, onmousemove, onmouseout, onmouseup, onfocus, onblur, onkeydown, onkeyup, onkeypress.

In addition, you can specify client-side events for any type of a TreeTable column or for a group of columns. All event-related attributes are listed below:

  Part of column  
Attributes
Entire column onclick, ondblclick, onmousedown, onmouseover, onmousemove, onmouseout, onmouseup
Column header headerOnclick, headerOndblclick, headerOnmousedown, headerOnmouseover, headerOnmousemove, headerOnmouseout, headerOnmouseup
Column body bodyOnclick, bodyOndblclick, bodyOnmousedown, bodyOnmouseover, bodyOnmousemove, bodyOnmouseout, bodyOnmouseup
Column footer footerOnclick, footerOndblclick, footerOnmousedown, footerOnmouseover, footerOnmousemove, footerOnmouseout, footerOnmouseup

In case of column groups, the events declared for the group are applied to each column in the group, except the header and footer events those are applied to the group's header and footer cells respectively.

The <o:columns> tag also supports all above mentioned attributes. These attributes can be specified as value-binding expressions that use a column data variable specified in the var attribute of the <o:columns> tag.

The <o:singleNodeSelection> and <o:multipleNodeSelection> tags provide the onchange event. You can specify it by using the onchange attribute.

You can specify client-side events for the particular row or cell using the following attributes of the <o:row> and <o:cell> tags: onclick, ondblclick, onmousedown, onmouseover, onmousemove, onmouseout, onmouseup, onkeydown, onkeyup, onkeypress. When specify row or cell-specific client-side events, you can use request-scope variables of the TreeTable component (see the description of var, nodePathVar, nodeLevelVar, nodeHasChildrenVar, columnIndexVar and columnIdVar attributes in the section Request-Scope Variables).

Client-Side API

The TreeTable component has the following public client-side API methods:

            Method            
Description
clearSelection() Clears selection in a TreeTable on which this method is invoked. This method works with any selection mode.
isSelectionEmpty() Returns "true" if the TreeTable component has any selected nodes. This method works for any selection mode.
getSelectedNodeCount() Returns the number of selected nodes, or 0 if no nodes are selected. This method works for any selection mode (single or multiple).
getSelectedNodeKey() Returns a node key of the current selected node, or null if there is no selected node. The TreeTable must be in single selection mode.
setSelectedNodeKey(nodeKey) Selects a node with the node key specified in the nodeKey parameter. The TreeTable must be in single selection mode.
getSelectedNodeKeys() Returns an array of node key values of the current selected nodes. The TreeTable must be in multiple selection mode.
setSelectedNodeKeys(nodeKeys) Selects nodes with node key values that are passed in the nodeKeys array. The TreeTable must be in multiple selection mode.
getCurrentColumn() Returns the object identifying the column for which the column context menu is currently being shown (see the Displaying Column Menus section). This object currently has only one field named index, which is a zero-based index of the column in a list of currently-rendered columns.
focus() Gives the keyboard focus to the component on which this method is invoked.
blur() Removes the keyboard focus from the component on which this method is invoked.
Client-Side Node Keys

As you can see in the section above, there are several client-side API methods which receive or return node key values. These are the client-side node key values that allow to uniquely identify nodes, and they are calculated for each node by converting the respective server-side node key values to string by invoking their toString() method. See the Model Node Objects Requirements section to see how server-side row keys should be specified. Note that if server-side node keys are not specified explicitly, then node data objects are assumed to be the node key objects, and their string representations as calculated the toString() method will serve as client-side node keys.

Special Cases

Absolute or Relative Positioned Content With Quirks Mode

There's an Internet Explorer issue where the elements displayed with absolute or relative position displayed in table rows remain visible when the rows themselves are hidden, which can manifest itself as a "garbage" remaining on the screen when you collapse TreeTable nodes. This problem is applicable only for pages displayed with the quirks rendering mode (and not a strict or transitional rendering mode), and there's the following rule for solving this.

If your pages are designed for the quirks rendering mode and there are any elements with position: absolute or position: relative declarations in the TreeTable's cells, you should apply the ieNonStaticPositionFix CSS class to such elements to solve this issue. Here's a simple example.

<o:treeTable ...>
  <o:column>
    <h:graphicImage style="display: relative" styleClass="ieNonStaticPositionFix" .../>
  <o:column>
  ...
</o:treeTable>

Limitations

  • The TreeTable component cannot be used inside DataTable, TreeTable or any other JSF components that replicate their child components during rendering.
  • Dynamic columns cannot have filters.
  • OpenFaces components and components that extend UIInput and UICommand cannot be used in the <o:cell> tag if this cell is rendered several columns per row.
  • Resources from the <f:loadBundle> tag cannot be used inside Ajax-enabled components. Though this can easily be solved by using the <o:loadBundle> component. See the LoadBundle documentation.
  • Component binding of TreeTable and Column components cannot be used for session-scope bean
Clone this wiki locally