-
Notifications
You must be signed in to change notification settings - Fork 160
Tree Specification
-
3.3 Globalization/Localization
3.5 API
-
4.1. Automation
4.2. Manual tests
Team Name
Developer Name
Stefan Ivanov
- Peer Developer Name | Date:
- Stefan Ivanov | Date: 15 Feb 2021
- Konstantin Dinev | Date: 14 Apr 2021
- Platform Architect Name | Date:
Version | User | Date | Notes |
---|---|---|---|
1 | Viktor Slavov, Stefan Ivanov | Feb 15, 2021 | Initial Draft |
2 | Viktor Slavov | Feb 18, 2021 | Fix Link Formatting |
3 | Viktor Slavov | Mar 8, 2021 | Rework selection events |
4. | Viktor Slavov | Mar 29, 2021 | Update TreeNode API |
5. | Viktor Slavov | Apr 09, 2021 | Update test cases, finalize API, limitations |
6. | Viktor Slavov | Apr 19, 2021 | Update outdated snippets |
7. | Teodosia Hristodorova | Nov 20, 2023 | Add toggleNodeOnClick property |
The IgxTreeComponent
is a component that allows a developer to show a set of nodes in a hierarchical fashion. It allows end-users to easily navigating structured information e.g. a site map or documentation topics.
The igxTreeComponent
should primarily be used as a navigational component when visualizing a nested data structure.
The tree should have the following features out-of-the-box
- Rendering nested nodes in a hierarchical fashion, maintaining a parent-child relationship
- Expanding and collapsing node, so all crucial information can be clearly visible at all times
- Disabled nodes which do not support any user interaction (e.g. permission based tree view)
- Active nodes - a note marked as "active" is highlighted w/ a specific style (e.g. the current location on a site map)
- Selection
- 5.1. None - no selection through user input. API selection manipulation is still possible
- 5.2. BiState - each node has a checkbox through which it can be selected via user input. Each node has two states - selected or not. Supports multiple selection.
- 5.3. Cascading - selecting a node selects its child nodes. Partially selected collections mark the resp. nodes as indeterminate.
- Keyboard navigation, supporting all of the previously mention features
- Link support, when tree nodes should contain anchors (
<a>
tags) - Accessibility features - all nodes should have proper aria roles and be fully readable and traversable via screen readers
...
The tree should allow me, as an end-user, to understand the relationships between the various nodes and use it to navigate the hierarchy of content.
End-user stories:
- Story 1: As an end-user, I want to have the nodes organized in a clear hierarchy, so that I can understand their relationship with one another.
- Story 2: As an end-user, I want to have the nodes organized in a clear hierarchy, so that I can easily expand/collapse them and select the node I am looking for.
- Story 3: As an end-user, I want to be able to expand/collapse nodes, so that I can create a state with the most viable information for me on my screen.
- Story 4: As an end-user, I want to have animations when nodes are expanded/collapsed, so that their relationship with one another is more obvious.
- Story 5: As an end-user, I want to have a clear indication of the selected (active) node, so that I have a better understanding of the information I'm looking at on the rest of my screen.
- Story 6: As an end-user, I want to have a clear indication if some/all/none of the child nodes of a given node are selected, so that I have a clear understanding of the current selection of nodes.
- Story 7: As an end-user, I want to select a single node, so that I navigate to the content it offers.
- Story 8: As an end-user, I want to select multiple nodes, so that I can perform an operation on all of them at once.
- Story 9: As an end-user, I want to have a cascading selection of a parent node implicitly selecting all of its children, grandchildren etc., so that I can perform an operation on all of them at once.
- Story 10: As an end-user, I want to be able to quickly expand/collapse/select a node with mouse and keyboard, so that I have a variety of convenient ways to interact with the hierarchy.
- Story 11: As an end-user, I want to change a node's parent by dragging it to another one, so that I can reorganize the hierarchy.
- Story 12: As an end-user, I want to move a node by dragging it above/below a sibling one, so that I can reorder nodes at the same level of the hierarchy.
- Story 13: As an end-user, I want to have a clear visual indication when dragging a node, so that I can have the right expectancy of where a node would be placed upon dropping it.
- Story 14: As an end-user, I want to have a clear visual indication when a node is loading its information/children, so that I have expectancy in scenarios with remote data/load on demand.
The tree should allow me, as a developer, to visually represent the relationship between nodes in my data and use it to provide means for my users to navigate and edit it.
Developer Stories
- Story 1: As a developer, I want to be able to easily create a tree view declaring the node hierarchy.
- Story 2: As a developer, I want to have full control over a node's content, as well as its child nodes (declarative approach).
- Story 3: As a developer, I want to have an easy way to find a node inside of the control with out-of-the-box API.
- Story 4: As a developer, I want to expand/collapse one or more nodes programmatically.
- Story 5: As a developer, I want to enable/disable the selection of a single node.
- Story 6: As a developer, I want to enable/disable the selection of multiple nodes.
- Story 7: As a developer, I want to enable/disable cascading selection of nodes so that selecting a node, selects all nodes in the tree below it as well and the state of each node reflects the cumulative one of its children.
- Story 8: As a developer, I want to set a node's selection state programmatically.
- Story 9: As a developer, I want to set a node's selection state programmatically, even when selection through user interaction is disabled.
- Story 10: As a developer, I want to be able to perform custom handling on user interaction - node selection, expansion/collapsing.
- Story 11: As a developer, I want to be able to control the animation when nodes are expanded/collapsed.
- Story 12: As a developer, I expect that manipulating the data source would update the visualized tree accordingly.
- Story 13: As a developer, I want to be able to load data on demand to expedite initial load times.
- Story 14: As a developer, I want to be able to ensure accessibility e.g. via proper
aria
roles in different cases such as node having a link. - Story 15: As a developer, I want to be able to mark nodes as disabled, so they are ignore in user interaction.
- Story 16: As a developer, I want to mark a node as the tree's active node, styling it in a pre-defined way and marking it as a point of interest to the users.
- Story 17: As a developer, I want to be able to distinguish when the active node changes through user interaction.
- Story 18: As a developer, I want to be able to bind a node's expansion state to a data model and ensure consistency between the two.
- Story 19: As a developer, I want to be able to bind a node's selection state to a data model and ensure consistency between the two.
- Story 20: As a developer, I want to be able to template the expand/collapse indicators for the tree.
- Story 21: As a developer, I want to be able to specify how many expanded sibling nodes there can be (
singleBranchExpand
input). - Story 22: As a developer, I want to be able to specify if nodes could be expanded/collapsed when clicking over them (
toggleNodeOnClick
input).
Describe behavior, design, look and feel of the implemented feature. Always include visual mock-up
The IgxTreeComponent
should support the three display densities available for other components - 'comfortable'
, 'cosy'
and 'compact'
. They come with distinct node heights and padding.
** All use cases and variants above are also available for hand-off
Developers are able to declare the tree and its nodes by specifying the node hierarchy and iterating through a data set:
<!-- Standard example -->
<igx-tree>
<igx-tree-node *ngFor="let node of data" [data]="node" [expanded]="isNodeExpaded(node)" [selected]="isNodeSelected(node)">
{{ node.text }}
<img [src]="node.image" [alt]="node.imageAlt" />
<igx-tree-node *ngFor="let child of node.children" [data]="child" [expanded]="isNodeExpaded(child)" [selected]="isNodeSelected(child)">
{{ child.text }}
</igx-tree-node>
</igx-tree-node>
</igx-tree>
When a node should render a link, add igxTreeNodeLink
to the a
tag. This will make sure the proper aria
role
is assigned to the node's DOM
elements.
<igx-tree>
<igx-tree-node *ngFor="let node of data" [data]="node" [expanded]="isNodeExpaded(node)" [selected]="isNodeSelected(node)">
{{ node.text }}
<img [src]="node.image" [alt]="node.imageAlt" />
<igx-tree-node *ngFor="let child of node.children" [data]="child">
<a igxTreeNodeLink [href]="child.url" target="_blank">{{ child.text }}</a>
</igx-tree-node>
</igx-tree-node>
</igx-tree>
Nodes can be bound to a data model so that their expanded
and selected
states are reflected in the data.
<igx-tree (nodeSelection)="handleSelectionEvent($event)">
<igx-tree-node *ngFor="let node of data" [data]="node" [(expanded)]="node.expanded" [(selected)]="node.selected">
{{ node.text }}
<img [src]="node.image" [alt]="node.imageAlt" />
<igx-tree-node *ngFor="let child of node.children" [data]="child">
<a igxTreeNodeLink [href]="child.url" target="_blank">{{ child.text }}</a>
</igx-tree-node>
</igx-tree-node>
</igx-tree>
To render a tree you do not necessarily need a data set - developers can create individual nodes w/o binding them to data:
<!-- Simple example with hardcoded nodes -->
<igx-tree>
<igx-tree-node [expanded]="true" [selected]="false">
I am a parent node 1
<img [src]="hard_coded_src.webb" alt="Alt Text" />
<igx-tree-node [expanded]="true" [selected]="false">
I am a child node 1
<igx-tree-node>
<a igxTreeNodeLink href="https://google.com" target="_blank">
I am a child node of the child
</a>
</igx-tree-node>
</igx-tree-node>
</igx-tree-node>
<igx-tree-node [expanded]="false" [selected]="false">
I am a parent node 2
<img src="hard_coded_src.webb" alt="Alt Text" />
<igx-tree-node [expanded]="false" [selected]="false">
I am a child node 1
</igx-tree-node>
</igx-tree-node>
<igx-tree-node [expanded]="false" [selected]="false">
I am a parent node 3
<img src="hard_coded_src.webb" alt="Alt Text" />
<igx-tree-node [expanded]="false" [selected]="false">
I am a child node 1
</igx-tree-node>
</igx-tree-node>
<igx-tree-node [expanded]="false" [selected]="false" [disabled]="true">
This area is under construction.
</igx-tree-node>
</igx-tree>
When finding nodes, you can pass a custom comparer function in order to find the data
<igx-tree>
<igx-tree-node *ngFor="let node of data" [data]="node" [expanded]="isNodeExpaded(node)" [selected]="isNodeSelected(node)">
{{ node.text }}
<img [src]="node.image" [alt]="node.imageAlt" />
<igx-tree-node *ngFor="let child of node.children" [data]="child" [expanded]="isNodeExpaded(child)" [selected]="isNodeSelected(child)">
{{ child.text }}
</igx-tree-node>
</igx-tree-node>
</igx-tree>
export class MyTreeViewComponent {
public data: { [key: string]: any, valueKey: string } = MY_DATA;
@ViewChild(IgxTreeComponent, { read: IgxTreeComponent })
public tree;
findNode(valueKey: string) {
const comparer: (nodeData: any, node: IgxTreeNodeComponent) => boolean =
(data: any, node: IgxTreeNodeComponent) => node.data.valueKey === data;
const matchNodes: IgxTreeNode<{ [key: string]: any, valueKey: string }>[] = this.tree.findNodes(valueKey, comparer);
}
}
3.3. Globalization/Localization
Describe any special localization requirements such as the number of localizable strings, regional formats
Resource stings for the following:
- Default expand/collapse icon template label when collapsed -
ITreeResourceStrings.igx_expand
(Default (EN):"Expand"
) - Default expand/collapse icon template label when expanded -
ITreeResourceStrings.igx_collapse
(Default (EN):"Collapse"
)
The keyboard can be used to navigate through all nodes in the tree.
The control distinguishes two states - focused
and active
.
The focused node is where all events are fired and from where navigation will begin/continue. Focused nodes are marked with a distinct style.
The active node, in most cases, is the last node on which user interaction took place. Active nodes also have a distinct style. Active nodes can be used to better accent a node in that tree that indicates the app's current state (e.g. a current route in the app when using a tree as a navigation component).
In most cases, moving the focused node also moves the active node.
When navigating to nodes that are outside of view, if the tree (igx-tree
tag) has a scrollbar, scrolls the focused node into view.
When finishing state transition animations (expand/collapse), if the target node is outside of view AND if the tree (igx-tree
tag) has a scrollbar, scrolls the focused node into view.
When initializing the tree and a node is marked as active, if that node is outside of view AND if the tree (igx-tree
tag) has a scrollbar, scrolls the activated node into view.
FIRST and LAST node refers to the respective visible node WITHOUT expanding/collapsing any existing node.
Disabled nodes are not counted as visible nodes for the purpose of keyboard navigation.
Keys | Description | Activates Node |
---|---|---|
ARROW DOWN | Moves to the next visible node. Does nothing if on the LAST node. | true |
CTRL + ARROW DOWN | Performs the same as ARROW DOWN. | false |
ARROW UP | Moves to the previous visible node. Does nothing if on the FIRST node. | true |
CTRL + ARROW UP | Performs the same as ARROW UP. | false |
TAB | Navigate to the next focusable element on the page, outside of the tree.* | false |
SHIFT + TAB | Navigate to the previous focusable element on the page, outside of the tree.* | false |
HOME | Navigates to the FIRST node. | true |
END | Navigates to the LAST node. | true |
ARROW RIGHT | On an expanded parent node, navigates to the first child of the node. If on a collapsed parent node, expands it. | true |
ARROW LEFT | On an expanded parent node, collapses it. If on a child node, moves to its parent node. | true |
SPACE | Toggles selection of the current node. Marks the node as active. | true |
* | Expand the node and all sibling nodes on the same level w/ children | true |
CLICK | Focuses the node | true |
When selection is enabled, end-user selection of nodes is only allowed through the displayed checkbox. Since both selection types allow multiple selection, the following mouse + keyboard interaction is available:
Combination | Description | Activates Node |
---|---|---|
SHIFT + CLICK / SPACE | when multiple selection is enabled, toggles selection of all nodes between the active one and the one clicked while holding SHIFT. | true |
Get
Name | Description | Type |
---|---|---|
rootNodes | Returns all of the tree's nodes that are on root level | IgxTreeNodeComponent[] |
Name | Description | Type |
---|---|---|
selection | The selection state of the tree |
"None" | "BiState" | "Cascading"
|
animationSettings | The setting for the animation when opening / closing a node | { openAnimation: AnimationMetadata, closeAnimation: AnimationMetadata } |
singleBranchExpand | Whether a single or multiple of a parent's child nodes can be expanded. Default is false
|
boolean |
toggleNodeOnClick | Whether clicking over nodes will change their expanded state or not. Default is false
|
boolean |
expandIndicator | Get\Set a reference to a custom template that should be used for rendering the expand/collapse indicators of nodes. | TemplateRef<any> |
displayDensity | Get\Set the display density of the tree. Affects all child nodes | DisplayDensity |
Name | Description | Parameters | Returns |
---|---|---|---|
findNodes | Returns an array of nodes which match the specified data. [data] input should be specified in order to find nodes. A custom comparer function can be specified for custom search (e.g. by a specific value key). Returns null if no nodes match |
data: T|, comparer?: (data: T, node: IgxTreeNodeComponent<T>) => boolean |
IgxTreeNodeComponent<T>[] | null
|
deselectAll | Deselects all nodes. If a nodes array is passed, deselects only the specified nodes. Does not emit nodeSelection event. |
nodes?: IgxTreeNodeComponent[] |
void |
collapseAll | Collapses the specified nodes. If no nodes passed, collapses all parent nodes. | nodes?: IgxTreeNodeComponent[] |
void |
expandAll | Sets the specified nodes as expanded. If no nodes passed, expands all parent nodes. | nodes?: IgxTreeNodeComponent[] |
void |
Name | Description | Cancelable | Arguments |
---|---|---|---|
nodeSelection | Emitted when item selection is changing, before the selection completes | true | { owner: IgxTreeComponent, newSelection: IgxTreeNodeComponent<any>[], oldSelection: IgxTreeNodeComponent<any>[], added: IgxTreeNodeComponent<any>[], removed: IgxTreeNodeComponent<any>[], cancel: true } |
nodeCollapsed | Emitted when node collapsing animation finishes and node is collapsed. | false | { node: IgxTreeNodeComponent<any>, owner: IgxTreeComponent } |
nodeCollapsing | Emitted when node collapsing animation starts, when node.expanded is set to transition from true to false . |
true | { node: IgxTreeNodeComponent<any>, owner: IgxTreeComponent, cancel: boolean } |
nodeExpanded | Emitted when node expanding animation finishes and node is expanded. | false | { node: IgxTreeNodeComponent<any>, owner: IgxTreeComponent } |
nodeExpanding | Emitted when node expanding animation starts, when node.expanded is set to transition from false to true . |
true | node: IgxTreeNodeComponent<any>, owner: IgxTreeComponent, cancel: boolean } |
activeNodeChanged | Emitted when the tree's active node changes |
false | IgxTreeNodeComponent<any> |
onDensityChanged | Emitted when the display density of the tree is changed | false | { oldDensity: DisplayDensity, newDensity: DisplayDensity } |
Get
Name | Description | Type |
---|---|---|
parentNode | The parent node of the current node (if any) | IgxTreeNodeComponent<any> |
path | The full path to the node, starting from the top-most ancestor | IgxTreeNodeComponent<any>[] |
level | The "depth" of the node. If root node - 0, if a child of parent - parent.level + 1 |
number |
tree | A reference to the tree the node is a part of | IgxTreecomponent |
children | A collection of child nodes. null if node does not have children |
IgxTreeNodeComponent<any>[] | null
|
Name | Description | Type |
---|---|---|
disabled | Get/Set whether the node is disabled. Disabled nodes are ignore for user interactions. | boolean |
expanded | The node expansion state. Does not trigger animation. |
boolean | null
|
selected | The node selection state. | boolean |
data | The data entry that the node is visualizing. Required for searching through nodes. | T |
active | Marks the node as the tree's active node | boolean |
resourceStrings | An accessor for the current resource strings used for the node | ITreeResourceStrings |
loading | Specifies whether the node is loading data. Loading nodes do not render children. To be used for load-on-demand scenarios | boolean |
Name | Description | Parameters | Returns |
---|---|---|---|
expand | Expands the node, triggering animations | None | void |
collapse | Collapses the node, triggering animations | None | void |
toggle | Toggles node expansion state, triggering animations | None | void |
Name | Description | Cancelable | Parameters |
---|---|---|---|
expandedChange | Emitted when the node's expanded property changes |
false | boolean |
selectedChange | Emitted when the node's selected property changes |
false | boolean |
- Should render tree w/ nodes
- Should only render nodes inside of tree (no other elements)
- Should support multiple levels of nesting (igx-tree-node under igx-tree-node)
- Should calculate nodes'
path
andlevel
correctly, depending on data hierarchy - Should not render collapsed node's children
- Should not render expand indicator if node has no children
- Should not render expand indicator if node is loading
- Should not render children if node is loading
- Should not render default select indicator if selection mode is
'None'
- Should render default indicator for expansion properly depending on node state
- Should render default select marker properly depending on node state
- Should accept template for expansion indicator
- Should allow overriding
animationSettings
that are used for node toggle - Should render nodes correctly depending on
displayDensity
settings - Should support searching for node children w/
tree.findNodes(data: any)
, returningnull
if no nodes match criteria - Should support searching for node children w/
tree.findNodes(data: any, comparer?: () => boolean)
w/ custom comparer - Should render links inside node w/
igxTreeNodeLink
directive
- Should collapse nodes when user interacts w/ indicator and
node.expanded === false
- Should expand nodes when user interacts w/ indicator and
node.expanded === true
- Should emit
ing
anded
events when node state is toggled - Should collapse all child nodes when collapsing a node
- Should collapse sibling nodes when
singleBranchExpand === true
- Should expand/collapse nodes when clicking over them if
toggleNodeOnClick === true
- Should collapse nodes w/o animation when
node.expanded
is set tofalse
- Should expand nodes w/o animation when
node.expanded
is set totrue
- Should expand nodes w/ animation when
node.expand()
is called - Should collapse nodes w/ animation when
node.collapse()
is called - Should toggle node state w/ animation when
node.toggle()
is called - Should emit node's
expandedChange
whennode.expanded
changes - Should support two-way binding for
node.expanded
- Should be able to change selection type to all 3 options ('None' (default), 'BiState', 'Cascading')
- Should deselect all selected nodes w/
tree.deselectNodes()
- Should deselect only specified nodes w/
tree.deselectNodes(node: IgxTreeNodeComponent<any>[])
- Should allow setting nodes as selected through API when
tree.selection === 'None'
- Should not render indicators when
tree.selection === 'None'
- Should select/deselect node by click on checkbox
- Should emit
nodeSelection
event w/ correct args when a node is selected / deselected - Should support multiple selection (e.g. newly selected nodes do not empty selected collection)
- Should emit node's
selectedChange
event whennode.selected
changes - Should support two-way binding for
node.selected
- Selecting a node should select its children
- Selecting all children of a parent should mark the parent as selected. All direct and non-direct parents should be affected correctly.
- Deselecting all children of a parent should mark the parent as deselected. All direct and non-direct parents should be affected correctly.
- Selecting a single child should mark the parent as indeterminate. All direct and non-direct parent should be affected correctly.
- Selecting the last non-selected child should mark the parent as selected and NOT indeterminate. All direct and non-direct parent should be affected correctly.
- Set nested child, that has its own children, as initially selected. Verify that direct and indirect parents have correct state.
- Partially selected parents should have the default indicator render as
indeterminate
- When selecting range of records using Shift + click key selection of parent should select all its children even if they are not in the selected range.
- In case that that there are already selected nodes in the tree, click on parent node , that is not selected, should select only the newly clicked node and its children and deselect the rest.
- In case that that there are already selected nodes in the tree, click on parent node that is not selected should add the node and its children to the selected rows collection even if child nodes are not in the selected range.
- Should focus and activate the first node on
Home
key press - Should focus and activate the last visible node on
End
key press - Should not navigate when node has no parent and node is collapsed on
Arrow Left
key press - Should navigate to parent node of a node w/
expanded === true
onArrow Left
key press, moving focus and active - Should collapsed expanded nodes on
Arrow Left
key press - Should not navigate when node has no children on
Arrow Right
key press - Should navigate to first child of an expanded on
Arrow Right
key press, moving focus and active - Should expand collapsed node w/ children on
Arrow Right
key press - Should focus and activate the next visible node on
Arrow Down
key press - Should only focus the next visible node on
Arrow Down + Ctrl
key press - Should focus and activate the previous visible node on
Arrow Up
key press - Should only focus the previous visible node on
Arrow Up + Ctrl
key press - Should expand all sibling nodes of the focused node on asterisk (
*
) key press - Should active the focused node on
Enter
key press - Should not prevent event's default behavior on
Enter
key press - Should perform nothing when
tree.selection === 'None'
onSpace
key press - Should select node when
tree.selection !== 'None'
onSpace
key press, moving active - Should select node range when
tree.selection !== 'None'
onSpace + Shift
keys press, moving active - Should emit
tree.activeNodeChange
when the active node changes - Should scroll to
active
node if tree has scrollbar and node is out of view - Should trigger events on links w/
igxTreeNodeLink
directive instead of parent
- Should render disabled nodes as not reachable for tab navigation (
tabIndex
should-1
) - Should not count disabled nodes as traversable nodes for keyboard navigation purposes
- If a node is expanded and all its children are disabled the focus and activation should not be moved from the node on
Arrow Right
key press - If a node is expanded and has enabled children the focus and activation should be moved to the first enabled child on
Arrow Right
key press - Pressing Arrow Up/Down should move the focus and activation to the previous/next enabled and visible node (if there is any) (skipping disabled)
- Pressing Asterisk on focused node should expand only the enabled and expandable nodes in the same group
- Should count children of collapsing nodes, transitioning from
expanded === true
tofalse
as non-traversable - Should count children of expanding nodes, transitioning from
expanded === false
totrue
as traversable - Should scroll active node into view when
tree.displayDensity
changes, tree has scroll and node is out of view as result of change - Should scroll container to
active
node if node state toggle animation pushes node out of view and tree has scroll
See aria-support
- Should render links in nodes
- Should dispatch events on links w/
igxTreeNodeLink
when navigating w/ keyboard - Should assign proper aria attributes on node when node does not have
igxTreeNodeLink
children - Should assign proper aria attributes on node when node has
igxTreeNodeLink
children - Should assign proper aria attributes on node when selection is enabled and node is selected
- Should assign proper aria label on node's expansion indicator depending on node's expansion state
- Should assign proper aria attributes if
igxTreeNodeLink
children are projected inside node'sng-content
via*ngTemplateOutlet
See navigation
- Check if tree is rendered correctly
- Create nodes with
igxTreeNodeLink
directive. Check if events are fired on node's link - Create nodes with
igxTreeNodeLink
directive viang-template
, passing a parent node. Check if events are fired on node's link - Assign custom
animationSettings
to tree. Check if tree nodes use assigned animation when expanding / collapsing - Assign
animationSettings
w/ long ( >2000ms
) animation durations. Check if keyboard navigation on expanding / collapsing nodes respects keyboard restrictions for keyboard navigation - Create a node bound to
async
data. Trigger a request, set node'sloading
totrue
. Check if indicator renders. - Set tree's selection to
Cascading
. Check if selecting single/multiple nodes cover selection scenario from selection - Create tree w/ 3+ levels of depth, 5+ children for each node, each level. Check tree performance.
An igx-tree
will have role="tree"
. aria-labelledby
should be manually added if there is a label/ heading associated w/ the tree.
An igx-tree-node
's child will be held in a container w/ role="group"
.
An igx-tree-node
will have role="treeitem"
if there is no link w/ igxTreeNodeLink
directive specified in it.
If there is such a link (a
tag), the role="treeitem"
will go on the link (as it is the interactable component of the node).
A node's expanded state will be properly reflected in the node's aria-expanded
attribute.
The igx-tree
does not support recursively creating the igx-tree-nodes
via template. This is a limitation in place because of a bug in the Angular framework.
All of the nodes should be declared manually, meaning if you intend to visualize a very deep hierarchy, this would impact the size of your template file.
The tree is intended to be primarily used as a layout / navigational component. If a hierarchical data source with numerous levels of depth and homogenous data needs to be visualized, you could use the igx-tree-grid
There is an issue in Angular's View Engine (pre-Ivy) that prevents the tree from being used when enableIvy: false
is set in tsconfig.json
.
Link to issue
Tabbing into the tree w/ keyboard navigation, when the tree has a scrollbar, will first focus the igx-tree-node
element. This is the default behavior in FireFox.
It's reproducible in this simple example StackBlitz.
This can be resolve by simply putting an explicit tabIndex = -1
on the tree, but since it's default browser behavior, we omit it in initial implementation.
When creating an anchor (<a>
) child w/ our tab stop directive ([igxTreeNodeLink]) via ng-template
, the node would not normally recognize it's children. As a workaround, a ref to the parent node needs to be passed (<a [igxTreeNodeLink]="parentNode"
):
<igx-tree>
<igx-tree-node #nodeRef *ngFor="let node of data" [data]="node">
<!-- template outlet in node content -->
<ng-template *ngTemplateOutlet="nodeTemplate; context: { $implicit: node, node: nodeRef }">
</ng-template>
<igx-tree-node #nodeRef *ngFor="let childNode of node.children" [data]="childNode">
<!-- template outlet in node content -->
<ng-template *ngTemplateOutlet="nodeTemplate; context: { $implicit: childNode, node: nodeRef }">
</ng-template>
....
</igx-tree-node>
</igx-tree-node>
<!-- template is defined in the tree body -->
<ng-template #nodeTemplate let-data let-parent="nodeRef">
<!-- explicitly pass a reference to the parent node via `[igxTreeNodeLink]="parent"` -->
<a [igxTreeNodeLink]="parent" [href]="data.href">{{ data.label }}</a>
</ng-template>
</igx-tree>