A tree is a hierarchical component that gives users access to a hierarchical set of objects displayed in a the parent-child relationship.
Use a tree view to visually display hierarchical information. The user can expand, collapse, and select a tree node within a tree view.
A basic tree provides a tree structure with named nodes and an arrow to expand and collapse child nodes.
A tree can include icons to represent the type of nodes within that group. Icons appear between the collapse/expand arrow and the parent node title.
A checkbox tree features checkboxes between the collapse/expand arrow and the name to indicate whether a node is selected. A parent node with children that are both selected and not selected is shown with an “indeterminate” state.
Checkbox trees should not be used together with icons for the nodes. As with icon trees, make sure to put checkboxes on all nodes of a checkbox tree. Do not alternate between types of trees in a checkbox tree.
The styling of each piece of a tree node is consistent across the different types of trees.
Common terminology that explains tree behavior.
Click on a node in the tree to either “highlight” it or navigate to its relative content.
Choose items to apply an action. For example, selecting a checkbox in the tree.
Use the arrow to the left of a node to expand or collapse a node in the tree.
To expand or collapse a parent node, the user clicks on the expand/collapse arrow. Clicking on the node item itself does not expand or collapse a node. It serves as a highlighting mechanism.
In read-only trees where highlighting is not an option, this pattern remains true for consistency.
To navigate to a content area based on a tree node or to highlight a tree node in order to take a subsequent action based on the selection, a user clicks on the node title itself.
With a checkbox tree, a user is able to perform one or a combination of three actions by clicking on one of three distinct targets:
- Expanding and Collapsing: a user is able to perform this action by clicking on the expand / collapse arrow.
- Checking a Checkbox: this would require clicking on the checkbox itself to check or uncheck a treenode. This will also affect the status of the parent node’s checkbox.
- Highlighting Tree Node: a user can highlight a tree node by clicking on the name (label) of the tree node. This allows for the possibility of loading content based on selection to provide more information on a tree node.
The way to load data within the tree is based on the scenario in which the tree is being used.
With a dynamic tree, make sure to load the parent nodes first and then lazy load child nodes when requested.
A general goal to keep in mind is that you want to minimize the time a user needs to spend before their first interaction with the tree as well as every subsequent interaction afterwards.
A basic tree can be created by simply nesting
clr-tree-node components at will. To pre-expand a node, you can use the
Use two-way binding
[(clrExpanded)]="expanded" on the clrExpanded property to track when a node is expanded or collapsed.
.clr-treenode-link class to style content inside of a Tree Node as clickable. Indicate an active Tree Node with the
.active class combined with the
When the tree structure is large and complex you can use iteration to generate nodes and child nodes based on the structure given to the ClrTree.
Use checkbox when nodes of the tree need to be selected or unselected by users. There are three parts that are needed to implement a ClrTree with checkbox controls.
- Data structured in a tree hierarchy
- The correct declaration on the ClrTreeNode's that need to be selectable
- A ClrSelectedState for each node that is selectable
If you know a specific node can never become indeterminate, you probably want to use a boolean property on your node. As mentioned previously,
[(clrSelected)] always outputs ClrSelectedState enum values, making two-way binding with a boolean problematic. The most straightforward solution is to use the de-sugarized syntax of the two-way binding , transforming the output to a boolean directly.
If the data you are displaying is recursive or has an unknown depth, you can use our
*clrRecursiveFor structural directive to recursively iterate over your data. It has the same syntax as
*ngFor, and accepts an additional
getChildren parameter that receives a node and should return its children. Please note that it needs to be used inside of a
<clr-tree> to function properly.
If your tree is too large to be fully build on initialization or getting the children of a node is an expensive operation like an HTTP request, you might want to lazy-load tree nodes, only loading the ones that are currently displayed. To lazy-load children for a simple tree component, you need to combine several features as follows:
- Use our
<clr-tree>root component, giving it a
- leverage our
*clrIfExpandedstructural directive, it only instantiates children when they are displayed
- listen to the
(clrIfExpandedChange)output to fetch the children's data
- add a
[clrLoading]boolean input to the node if fetching children is asynchronous, to display a spinner while waiting for the data to be loaded
Lazy-loading data for recursive trees is actually the simplest case: as soon as you set
[clrLazy]="true" on the parent
getChildren function will only be lazily called when a node becomes expanded, and supports both
Observable return types if you need to fetch children asynchronously.
By default, recursive trees will pre-load on level ahead to know if the currently displayed nodes are expandable of not. If you do not want this behavior and have a way of knowing if a node is expandable without fetching its children, you can prevent the extra loading by using the
[clrExpandable] boolean input on nodes based on your own condition.