Visualizing data with tree

The tree component visualizes hierarchical data in the tree format.

How to do it…

The data for tree is provided as instances of org.primefaces.model.TreeNode, which correspond to the nodes in the tree. A pure client-side tree might be useful to create tree-based navigation menus. A basic data model for a tree could be constructed as follows:

TreeNode root = new DefaultTreeNode("Root", null);
TreeNode node1 = new DefaultTreeNode("Node1", root);
TreeNode node2 = new DefaultTreeNode("Node2", root);
TreeNode node11 = new DefaultTreeNode("Node1.1", node1);
TreeNode node12 = new DefaultTreeNode("Node1.2", node1);
TreeNode node21 = new DefaultTreeNode("Node2.1", node2);
TreeNode node211 = new DefaultTreeNode("Node2.1.1", node21);

The definition of tree for the previously mentioned model will be as shown here:

<p:tree id="simple" value="#{treeDataBean.root}" var="node">
  <p:treeNode>
    <h:outputText value="#{node}" />
  </p:treeNode>
</p:tree>

The visual of the tree will be as shown in the following screenshot. By default, the nodes will not be expanded as given in the image; it's done for demonstration purposes.

How to do it…

There's more…

If the hierarchical data model of tree contains too many nodes, it would be useful to dynamically load the tree by setting the dynamic attribute to true in order to load a part of tree when requested by expanding a node with a click.

Also, by enabling caching with setting the cache attribute to true, expanding a previously loaded node will not result in an AJAX request to load its children again. Here's the code that encapsulates this discussion:

<p:tree id="dynamic" value="#{treeDataBean.root}" var="node"
  dynamic="true" cache="true">
  <p:treeNode>
    <h:outputText value="#{node}" />
  </p:treeNode>
</p:tree>

Node type support

It's possible to provide different visuals for each node with custom node definitions. To achieve this, the <p:treeNode> component could be used with defined node types. The following definition contains two node definitions—one for expandable nodes with type="node" and one for the leaf nodes with type="leaf". To differentiate the nodes visually, the tree nodes use the ui-icon-minusthick icon for leaf nodes and ui-icon-plusthick for expandable icons:

<p:tree id="customNodes" value="#{treeDataBean.rootWithType}"
  var="node">
  <p:treeNode type="node" icon="ui-icon-plusthick">
    <h:outputText value="#{node}" />
  </p:treeNode>
  <p:treeNode type="leaf" icon="ui-icon-minusthick">
    <h:outputText value="#{node}" />
  </p:treeNode>
</p:tree>

The integration is achieved with the type attribute where it matches the parameter given to DefaultTreeNode. The code to construct the model is given here:

rootWithType = new DefaultTreeNode("node", "Root", null);
TreeNode node1_type = new DefaultTreeNode("node", "Node1",
  rootWithType);
TreeNode node2_type = new DefaultTreeNode("node", "Node2",
  rootWithType);

TreeNode node11_type = new DefaultTreeNode("leaf", "Node1.1",
  node1_type);
TreeNode node12_type = new DefaultTreeNode("leaf", "Node1.2", 
  node1_type);

TreeNode node21_type = new DefaultTreeNode("node", "Node2.1",
  node2_type);
TreeNode node211_type = new DefaultTreeNode("leaf", "Node2.1.1",
  node21_type);

If you want the node to react to an expand/collapse action by changing its icon, you can use expandedIcon and collapsedIcon to display the different icons based on the status of the node.

The definition of the <p:treeNode> component with type set to node is given here with the aforementioned attributes:

<p:treeNode type="node" expandedIcon="ui-icon-minusthick" 
  collapsedIcon="ui-icon-plusthick">
  <h:outputText value="#{node}" />
</p:treeNode>

Node selection

The tree component provides built-in selection with a single node or multiple nodes or with a checkbox selection on the nodes. The selectionMode attribute enables selection with its value set to single for the single selection mode, multiple for multiple node selection, and checkbox to select nodes with checkboxes. The selected nodes are collected in the selection attribute as an instance of TreeNode or as an array of TreeNode instances. Here's the code that encapsulates this discussion:

<p:tree id="single" value="#{treeDataBean.root}" var="node"
  selectionMode="single"
  selection="#{treeDataBean.selectedNode}">
  <p:treeNode>
    <h:outputText value="#{node}" />
  </p:treeNode>
</p:tree>

<p:tree id="multiple" value="#{treeDataBean.root}" var="node"
  selectionMode="multiple"
  selection="#{treeDataBean.selectedNodes}">
  <p:treeNode>
    <h:outputText value="#{node}" />
  </p:treeNode>
</p:tree>

Note

PrimeFaces also provides the CheckboxTreeNode model class that differs from the DefaultTreeNode model class with its partialSelected property, where it provides hierarchical selection. In order to modify selection behaviors, you can set the propagateSelectionUp and propagateSelectionDown attributes of tree that propagate upward selection to the root element or downward selection to children, respectively.

It's also possible to select multiple nodes with a modifier key, which would be Ctrl in Windows and Command in MacOS.

Drag and drop

Reordering is possible between the nodes of a tree with drag and drop. It's also possible to drag nodes between multiple trees by placing them into a scope. Dragging and dropping within a tree is exemplified here:

<p:tree id="dnd" value="#{treeDataBean.root}" var="node"
  draggable="true" droppable="true">
  <p:treeNode>
    <h:outputText value="#{node}" />
  </p:treeNode>
</p:tree>

Dragging a node between different trees is exemplified here:

<p:tree id="dndSource" value="#{treeDataBean.root}" var="node"
  selectionMode="single"
  selection="#{treeDataBean.selectedNode1}"
  draggable="true" droppable="true" 
  dragdropScope="treeScope">
  <p:treeNode>
    <h:outputText value="#{node}" />
  </p:treeNode>
</p:tree>

<p:tree id="dndTarget" value="#{treeDataBean.root2}" var="node"
  selectionMode="single"
  selection="#{treeDataBean.selectedNode2}"
  draggable="true" droppable="true"
  dragdropScope="treeScope">
  <p:treeNode>
    <h:outputText value="#{node}" />
  </p:treeNode>
</p:tree>

As seen in the code, dragdropScope should also be set to the same value for both trees. The draggable and droppable attributes of both trees could be set to true to enable drag and drop between the trees as well as between within the nodes of one tree.

Tip

Using drag and drop between multiple trees inside panel components might lead to problems with the current version of the framework. Try to implement the user interface by keeping it simple when drag and drop between trees is a requirement.

AJAX behavior events

The tree component supports AJAX behavior events in order to handle node expand/collapse or selection/unselection. The definition of the AJAX behavior events should be placed within the tree, as shown in the following code snippet:

<p:tree id="withAJAX" value="#{treeDataBean.root}" var="node"
  selectionMode="single"
  selection="#{treeDataBean.selectedNode}">
  <p:ajax event="expand" update=":mainForm:growl"
    listener="#{treeDataBean.onNodeExpand}" />
  <p:ajax event="collapse" update=":mainForm:growl"
    listener="#{treeDataBean.onNodeCollapse}" />
  <p:ajax event="select" update=":mainForm:growl"
    listener="#{treeDataBean.onNodeSelect}" />
  <p:ajax event="unselect" update=":mainForm:growl"
    listener="#{treeDataBean.onNodeUnselect}" />
  <p:treeNode>
    <h:outputText value="#{node}" />
  </p:treeNode>
</p:tree>

The events and their corresponding listener method's parameter types are given in the following table; for all the events, the tree can be accessed with the event.getNode() method call.

Action

Event name

Listener method parameter type

When a node is expanded

expand

org.primefaces.event.NodeExpandEvent

When a node is collapsed

collapse

org.primefaces.event.NodeCollapseEvent

When a node is selected

select

org.primefaces.event.NodeSelectEvent

When a node is unselected

unselect

org.primefaces.event.NodeUnselectEvent

Context menu support

The tree component easily integrates with the contextMenu component, and the context menu can be assigned to the nodes for a right-click event. It is also possible to assign different context menus with different tree nodes using the nodeType attribute.

There are two context menu definitions—one for the nodes of the tree that contain child nodes and the other one for the leaf nodes that have no child nodes. They are given here with the tree definition (the menus differ according to the given nodeType attribute):

<p:tree id="withContextMenu" var="node" selectionMode="single"
  value="#{treeDataBean.rootWithType}"
  selection="#{treeDataBean.selectedNode}">
  <p:treeNode type="node">
    <h:outputText value="#{node}" />
  </p:treeNode>

  <p:treeNode type="leaf">
    <h:outputText value="#{node}" />
  </p:treeNode>
</p:tree>

<p:contextMenu for="withContextMenu" nodeType="node">
  <p:menuitem value="View" update="dialogPanel"
    icon="ui-icon-search"
    oncomplete="PF('nodeDialog').show()" />
</p:contextMenu>

<p:contextMenu for="withContextMenu" nodeType="leaf">
  <p:menuitem value="View" update="dialogPanel"
    icon="ui-icon-search"
    oncomplete="PF('nodeDialog').show()" />
  <p:menuitem value="Delete"
    actionListener="#{treeDataBean.deleteNode}"
    update="withContextMenu" icon="ui-icon-close" />
</p:contextMenu>

While only displaying the context menu with the view and delete actions for the leaf nodes of the tree, the context menu with just a view action will be displayed for the nodes that contain child nodes.

Horizontal layout

With the orientation attribute, it's possible to set the layout of the nodes as horizontal by setting the attribute to horizontal. The default value of the attribute is vertical. The visual output of the horizontal layout is given here. By default, the nodes will not be expanded as given in the image; it's done for demonstration purposes.

Horizontal layout

PrimeFaces Cookbook Showcase application

This recipe is available in the demo web application on GitHub (https://github.com/ova2/primefaces-cookbook/tree/second-edition). Clone the project if you have not done it yet, explore the project structure, and build and deploy the WAR file on application servers compatible with Servlet 3.x, such as JBoss WildFly and Apache TomEE.

The showcase for the recipe is available at http://localhost:8080/pf-cookbook/views/chapter5/tree.jsf.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.205.136