Tree Specification - IgniteUI/igniteui-webcomponents Wiki

Tree Specification

Contents

  1. Overview

  2. User Stories

  3. Functionality

    3.1 End-user Expereince

    3.2 Developer Experience

    3.3 Globalization/Localization

    3.4 Keyboard Navigation

  4. Test Scenarios

  5. Accessibility

  6. Assumptions and Limitations

  7. References

Owned by

Team Name: Astrea

Developer Name: Martin Evtimov, Monika Kirkova

Designer Name:

Requires approval from

Signed off by

Revision History

Version Users Date Notes
1

1. Overview

The <igc-tree> allows users to represent hierarchical data in a tree-view structure, maintaining parent-child relationships, as well as to define static tree-view structure without a corresponding data model.

<igc-tree>
    <igc-tree-item *ngFor="let item of data" [value]="item" [expanded]="isItemExpanded(item)" [selected]="isItemSelected(item)">
        {{ item.text }}
        <img [src]="item.image" alt="item.imageAlt" />
        <igc-tree-item*ngFor="let child of item.children" [value]="child" [expanded]="isItemExpanded(child)" [selected]="isItemSelected(child)">
            {{ child.text }}
            <igc-tree-item *ngFor="let leafChild of child.children" [value]="leafChild" [expanded]="isItemExpanded(leafChild)" [selected]="isItemSelected(leafChild)">
                <a href="{{leafChild.location}}" target="_blank">{{ leafChild.text }}</a>
            </igc-tree-item>
        </igc-tree-item>
    </igc-tree-item>
</igc-tree>

Objectives

The <igc-tree> should primarily be used as a navigational component when visualizing a nested data structure. The control is not data-bound and takes a declarative approach, giving users more control over what is being rendered.

Acceptance criteria

The tree should have the following features out-of-the-box

  1. Rendering nested items in a hierarchical fashion, maintaining a parent-child relationship
  2. Expanding and collapsing items, so all crucial information can be clearly visible at all times
  3. Disabled items which do not support any user interaction (e.g. permission-based tree view)
  4. Active items - a note marked as "active" is highlighted w/ a specific style (e.g. the current location on a site map)
  5. Selection
    • 5.1. None - no selection through user input. API selection manipulation is still possible
    • 5.2. Multiple - each item has a checkbox through which it can be selected via user input. Each item has two states - selected or not. Supports multiple selection.
    • 5.3. Cascading - selecting an item selects its child items. Partially selected collections mark the resp. items as indeterminate.
  6. Keyboard navigation, supporting all of the previously mention features
  7. Accessibility features - all items should have proper aria roles and be fully readable and traversable via screen readers

2. User Stories

Developer stories:

End-user stories:

The tree should allow me, as an end-user, to understand the relationships between the various items and use it to navigate the hierarchy of content.

3. Functionality

Describe behavior, design, look and feel of the implemented feature. Always include visual mock-up

3.1. End-User Experience

The IgcTreeComponent should support the three display sizes available for other components - 'small', 'medium' and 'large'(default). They come with distinct item heights and padding.

** All use cases and variants above are also available for hand-off

3.2. Developer Experience

Simple tree iterating data:

Developers are able to declare the tree and its items by specifying the item hierarchy and iterating through a data set:

<!-- Standard example -->
<igc-tree>
    <igc-tree-item *ngFor="let item of data" [value]="item" [expanded]="isItemExpaded(item)" [selected]="isItemSelected(item)">
        {{ item.text }}
	<img [src]="item.image" [alt]="item.imageAlt" />
	<igc-tree-item *ngFor="let child of item.children" [value]="child" [expanded]="isItemExpaded(child)" [selected]="isItemSelected(child)">
	    {{ child.text }}
	</igc-tree-item>
    </igc-tree-item>
</igc-tree>

Simple tree w/ links

When an item should render a link, add disableTab to the <igc-tree-item> tag. This will make sure the proper aria role is assigned to the item's DOM elements.

<igc-tree>
    <igc-tree-item *ngFor="let item of data" [value]="item" [expanded]="isItemExpaded(item)" [selected]="isItemSelected(item)">
        {{ item.text }}
	<img [src]="item.image" [alt]="item.imageAlt" />
	<igc-tree-item *ngFor="let child of item.children" [value]="child" [disableTab]="true">
	    <a [href]="child.url" target="_blank">{{ child.text }}</a>
	</igc-tree-item>
    </igc-tree-item>
</igc-tree>

Two-way data binding item states

Tree items can be bound to a data model so that their expanded and selected states are reflected in the data.

<igc-tree (igcSelection)="handleSelectionEvent($event)">
    <igc-tree-item *ngFor="let item of data" [value]="item" [(expanded)]="item.expanded" [(selected)]="item.selected">
        {{ item.text }}
	<img [src]="item.image" [alt]="item.imageAlt" />
	<igc-tree-item *ngFor="let child of item.children" [value]="child">
	    <a [href]="child.url" target="_blank">{{ child.text }}</a>
	</igc-tree-item>
    </igc-tree-item>
</igc-tree>

Tree w/ hardcoded items

To render a tree you do not necessarily need a data set - developers can create individual items w/o binding them to data:

<!-- Simple example with hardcoded items -->
<igc-tree>
    <igc-tree-item [expanded]="true" [selected]="false">
        I am a parent item 1
	<img [src]="hard_coded_src.webb" alt="Alt Text" />
		
	<igc-tree-item [expanded]="true" [selected]="false">
	    I am a child item 1	    
	</igc-tree-item>
    </igc-tree-item>
	
    <igc-tree-item [expanded]="false" [selected]="false">
        I am a parent item 2
	<img src="hard_coded_src.webb" alt="Alt Text" />
		
	<igc-tree-item [expanded]="false" [selected]="false">
	    I am a child item 1
	</igc-tree-item>
    </igc-tree-item>
</igx-tree>

Finding tree items

When finding items, you can pass a custom comparer function in order to find the value

<igc-tree>
    <igc-tree-item *ngFor="let item of data" [value]="item" [expanded]="isItemExpaded(item)" [selected]="isItemSelected(item)">
        {{ item.text }}
	<img [src]="item.image" [alt]="item.imageAlt" />
	<igc-tree-item *ngFor="let child of item.children" [value]="child" [expanded]="isItemExpaded(child)" [selected]="isItemSelected(child)">
            {{ child.text }}
	</igc-tree-item>
    </igc-tree-item>
</igc-tree>
export class MyTreeViewComponent {
  public value: { [key: string]: any, valueKey: string } = MY_VALUE;
  @ViewChild(IgcTreeComponent, { read: IgcTreeComponent })
  public tree;

  findItem(valueKey: string) {
    const comparer: (itemValue: any, item: IgcTreeItemComponent) => boolean =
      (value: any, Item: IgcTreeItemComponent) => item.value.valueKey === value;
    const matchItems: IgcTreeItem<{ [key: string]: any, valueKey: string }>[] = this.tree.findItems(valueKey, comparer);
  }
}

3.3. Globalization/Localization

Describe any special localization requirements such as the number of localizable strings, regional formats

3.4. Keyboard Navigation

The keyboard can be used to navigate through all items in the tree. The control distinguishes two states - focused and active. The focused item is where all events are fired and from where navigation will begin/continue. Focused items are marked with a distinct style. The active item, in most cases, is the last item on which user interaction took place. Active items also have a distinct style. Active items can be used to better accent an item 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 item also moves the active item.

When navigating to items that are outside of view, if the tree (igc-tree tag) has a scrollbar, scrolls the focused item into view. If the target item is outside of view AND if the tree (igc-tree tag) has a scrollbar, scrolls the focused item into view. When initializing the tree and an item is marked as active, if that item is outside of view AND if the tree (igc-tree tag) has a scrollbar, scrolls the activated item into view.

FIRST and LAST item refers to the respective visible item WITHOUT expanding/collapsing any existing item.

Disabled items are not counted as visible items for the purpose of keyboard navigation.

Keys Description Activates Item
ARROW DOWN Moves to the next visible item. Does nothing if on the LAST tree item. true
CTRL + ARROW DOWN Performs the same as ARROW DOWN. false
ARROW UP Moves to the previous visible item. Does nothing if on the FIRST tree item. true
CTRL + ARROW UP Performs the same as ARROW UP. false
TAB Navigate to the next focusable element on the page* false
SHIFT + TAB Navigate to the previous focusable element on the page* false
HOME Navigates to the FIRST tree item. true
END Navigates to the LAST tree item. true
ARROW RIGHT On an expanded parent item, navigate to the first child of the item. If on a collapsed parent item, expand it. true
ARROW LEFT On an expanded parent item, collapses it. If on a child item, moves to its parent item. true
SPACE Toggles selection of the current tree item. Marks the tree item as active. true
* Expand the tree item and all sibling items on the same level w/ children true
CLICK Focuses the tree item true

When selection is enabled, end-user selection of tree items is only allowed through the displayed checkbox. Since both selection types allow multiple selection, the following mouse + keyboard interaction is available:

Combination Description Activates Item
SHIFT + CLICK / SPACE when multiple selection is enabled, toggles selection of all tree items between the active one and the one clicked while holding SHIFT. true

3.5 API

IgcTreeComponent

Accessors

Name Description Type
rootItems Returns all of the tree's items that are on root level IgcTreeItemComponent[]
selectedItems Returns a collection of all currently selected tree items IgcTreeItemComponent[]

Properties

Name Description Type Default value Reflected
selection The selection state of the tree. "None" | "Multiple" | "Cascading" "None" true
singleBranchExpand Whether a single or multiple of a parent's child items can be expanded. boolean false true
size Get\Set the size of the tree. Affects all child items small | medium | large large true

Methods

Name Description Parameters Returns
findItems Returns an array of tree items which match the specified value. [vallue] input should be specified in order to find items. A custom comparer function can be specified for custom search (e.g. by a specific value key). Returns null if no items match value: T|, comparer?: (value: T, item: IgcTreeItemComponent) => boolean IgcTreeItemComponent[] | null
deselect Deselects all items. If items array is passed, deselects only the specified items. Does not emit igcSelection event. items?: IgcTreeItemComponent[] void
select Selects all tree items. If items array is passed, selects only the specified items. Does not emit igcSelection event. items?: IgcTreeItemComponent[] void
collapse Collapses the specified tree items. If no items passed, collapses all parent items. items?: IgcTreeItemComponent[] void
expand Sets the specified tree items as expanded. If no items passed, expands all parent items. items?: IgcTreeItemComponent[] void

Events

Name Description Cancelable Arguments
igcSelection Emitted when item selection is changing, before the selection completes true { newSelection: IgcTreeItemComponent[], oldSelection: IgcTreeItemComponent[] }
igcItemCollapsed Emitted when tree item is collapsed. false { item: IgcTreeItemComponent }
igcItemCollapsing Emitted when tree item is collapsing, when item.expanded is set to transition from true to false. true { item: IgcTreeItemComponent }
igcItemExpanded Emitted when tree item is expanded. false { item: IgcTreeItemComponent }
igcItemExpanding Emitted when tree item expanding animation starts, when item.expanded is set to transition from false to true. true item: IgcTreeItemComponent, owner: IgcTreeComponent }
igcActiveItem Emitted when the tree's active item changes false IgcTreeItemComponent

Slots

Name Description
(default) Renders the tree.

IgcTreeItemComponent

Accessors

Name Description Type
parentItem The parent item of the current tree item (if any) IgcTreeItemComponent
path The full path to the tree item, starting from the top-most ancestor IgcTreeItemComponent[]
level The "depth" of the tree item. If root item - 0, if a child of parent - parent.level + 1 number
tree ? A reference to the tree the item is a part of IgcTreecomponent

Properties

Name Description Type Default value Reflected
disabled Get/Set whether the tree item is disabled. Disabled items are ignored for user interactions. boolean false true
expanded The tree item expansion state. boolean | null false true
selected The tree item selection state. boolean false true
value The value entry that the tree item is visualizing. Required for searching through items. T
active Marks the item as the tree's active item boolean false true
loading ? Specifies whether the item is loading data. Loading items do not render children. To be used for load-on-demand scenarios boolean false true

Methods

Name Description Parameters Returns
expand Expands the tree item None void
collapse Collapses the tree item None void
toggle Toggles tree item expansion state None void

| getChildren | Returns a collection of child items. If the parameter value is true returns all tree item's direct children, otherwise - only the direct children. | boolean |IgxTreeItemComponent[]|\

Slots

Name Description
(default) Renders the tree item.
content The tree item container.
expandIndicator The expand indicator container.
indentation The container (by default the space) before the tree item.

4. Test Scenarios

Automation

Basic

Expand/Collapse

Selection

None

Multiple

Cascading

Tri-state Navigation

Keyboard Navigation

Basic

Disabled item tests

5. Accessibility

ARIA Support Tree Aria example

An igc-tree will have role="tree". aria-labelledby should be manually added if there is a label/ heading associated w/ the tree.

An igc-tree-item's child will be held in a container w/ role="group".

An igc-tree-item will have role="treeitem" if its disableTab property is not enabled. If it is enabled, the role="treeitem" will go on the child element.

A item's expanded state will be properly reflected in the item's aria-expanded attribute.

RTL Support

6. Assumptions and Limitations

Assumptions Limitation Notes

7. References