-
Notifications
You must be signed in to change notification settings - Fork 160
Tree Specification
Team Name
Developer Name
Stefan Ivanov
- Peer Developer Name | Date:
- Stefan Ivanov | Date: 15 Feb 2021
- Product Owner Name | Date:
- Platform Architect Name | Date:
Version | User | Date | Notes |
---|---|---|---|
1 | Viktor Slavov, Stefan Ivanov | Feb 15, 2021 | Initial Draft |
The IgxTreeComponent
is a component allowing a developer user to show a set of items in a hierarchical fashion allowing his end-users to use them for easily navigating structured information e.g. a site map of a website or documentation topics.
The igxTreeComponent
should primarily be used as a navigational component when visualizing a nested data structure.
- have hierarchical data visualized in a pleasing and easy-to-navigate way
- be able to expand and collapse tree nodes so I can always have only the most viable information visible on my screen
- have a visually pleasing transition between opened and closed node states
- have a node highlighted to better keep track of the information I'm looking at (active node)
- be able to quickly navigate through and expand/collapse nodes of the tree using a mouse
- be able to quickly navigate through and expand/collapse nodes of the tree using a keyboard
- mark a single node as selected, using my mouse and a specific UI part
- mark a single node as selected, using my keyboard
- mark a single node as selected, also marking all of its descendants
- have a visual indicator if:
- a node is selected
- if all of a node's descendants are marked as selected
- if some of a node's descendants are marked as selected
- if none of a node's descendants are marked as selected
- be able to rearrange data in via drag and drop, considering that I can achieve the following:
- move a node to a different parent
- rearrange nodes under the same parent
- have a visual indicator of the expected result of my drag-and-drop interaction
- be able to discern when a node's information is being loaded (load-on-demand scenario)
- be able to quickly create a tree view declaring the node hierarchy
- have full control over a node's content, as well as it's child nodes (declarative)
- have an easy way to find a node inside of the control with OOB API
- expand/collapse a single or multiple nodes programmatically
- enable/disable selection for nodes and differentiate between selection scenarios:
- selecting a node marks only the focused node for as selection
- selecting a node marks the focused node and all child nodes as selected
- set a node's selection state programmatically
- be able to perform custom handling on user interaction - node selection, toggling
- be able to control the opening / closing animation of nodes
- be able to manipulate the visualized tree by manipulating the my data source
- be able to load data on demand to expediate initial load times
- be able to ensure proper
aria
roles in the different cases (e.g. node has a link)
<!-- Standard example -->
<igx-tree>
<igx-tree-node *ngFor="let nodes 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 nodes 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>
<!-- 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-url-node [url]="https://google.com">
I am a child node of the child
</igx-tree-url-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>
When finding nodes, you can pass a custom comparer function in order to find the data
<igx-tree>
<igx-tree-node *ngFor="let nodes 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) => nodeData.valueKey === data;
this.tree.findData(valueKey, comparer);
}
}
- TBD
- TBD
- TBD
- TBD
Keyboard can be used to navigate through all nodes in the tree. FIRST and LAST node refers to the respective visible node WITHOUT expanding/collapsing any existing node
- ARROW DOWN moves to the next visible node. Does nothing if on the LAST node.
- ARROW UP moves to the previous visible node. Does nothing if one the FIRST node.
- TAB performs the same as ARROW DOWN. If on the LAST node, moves to the next element w/ tabIndex outside of the tree.
- SHIFT + TAB performs the same as ARROW UP. If on the FIRST node, moves to the previous element w/ tabIndex outside of the tree.
- HOME navigates to the FIRST node.
- END navigates to the LAST node.
- ARROW RIGHT on an expanded parent node navigates to the first child of the node.
- ARROW LEFT on a child node navigates to the parent node.
Node expanded state can be toggled via keyboard interaction w/ ARROW KEYS.
- ARROW LEFT collapses and expanded node. If the node is already collapsed and is not a child node itself - does nothing.
- ARROW RIGHT expands a collapsed node. If the node is already expanded - moves to the first child node.
When selection is enabled, node can be selected via keyboard interaction.
- SPACE toggles a node's selection state (selected/deselected).
Get
Name | Description | Type |
---|---|---|
id | The unique id of the tree node. Used for state management and selection. | string |
parentNode | The parent node of the current node (if any) | IgxTreeNodeComponent |
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 | IgxTree |
children | A collection of child nodes. null if node does not have children |
any[] | null
|
role | The role attribute assigned to the rendered igx-tree-node DOM element |
string |
Name | Description | Type |
---|---|---|
expanded | If the node is expanded |
boolean | null
|
selected | If the node is selected | boolean |
data | The data entry that the node is visualizing. Required for searching through nodes | any |
Get
Name | Description | Type |
---|---|---|
id | The unique id of tree (not bound to the id html attribute ) |
string |
Name | Description | Type |
---|---|---|
selection | The selection state of the tree | "None" |
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 |
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
|
selectAll | Sets the specified nodes as selected, clearing the previous selection. If no nodes passed, selects all visible (expanded parents and leaf) nodes | nodes?: IgxTreeNodeComponent[] |
void |
expandAll | Sets the specified nodes as expanded. If no nodes passed, expands all visible parent nodes | nodes?: IgxTreeNodeComponent[] |
void |
Name | Description | Cancelable | Parameters |
---|---|---|---|
selection | Emitted when item selection is changing, before the selection completes | true | owner: IgxTreeComponent, selectedNodes: IgxTreeComponent[] |
nodeOpening | Emitted before the a node is opened. | true | node: IgxTreeNodeComponent, owner: IgxTreeComponent, cancel: boolean |
nodeOpened | Emitted after the a node is opened. | false | node: IgxTreeNodeComponent, owner: IgxTreeComponent |
nodeClosing | Emitted before the a node is closed. | true | node: IgxTreeNodeComponent, owner: IgxTreeComponent, cancel: boolean |
nodeClosed | Emitted after the a node is closed. | false | node: IgxTreeNodeComponent, owner: IgxTreeComponent |
nodeDragStart | Emitted when a node drag is stared | true | IDragStartEventArgs & { node: IgxTreeNodeComponent } |
nodeDragMove | Emitted when the cursor moves while a node dragged | true | IDragMoveEventArgs & { node: IgxTreeNodeComponent } |
nodeDrop | Emitted when a node is dropped | false | IDragDropEventArgs & { node: IgxTreeNodeComponent } |
- 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 not render collapsed node's children
- Should not render expand indicator if node has no children
- 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 accept template for select marker
- Should collapse nodes
- Should expand nodes
- Should collapse all child nodes when collapsing a node
- Should collapse sibling nodes when
singleBranchExpand === true
- Should be able to change selection type to all 3 options ('None' (default), 'BiState', 'Cascading')
- Should select nodes
- Should deselect nodes
- Should be able to set the node selection and clear the previous selection (
setSelection
)
- Partially selected parents should have the default indicator render as
indeterminate
- Selecting a node should select its children
- Selecting a child should mark its parent node as partially selected
- Selecting the last non-selected child should mark the parent as selected
- Deselecting a selected child under a selected parent should mark the parent as partially selected
See navigation
See aria-support
- Rendered tree and nodes have expected aria attributes
- Passing a link child in a node w/
igxTreeNodeLink
directive should change aria roles of the the node
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