0 votes
in Angular Material by
Explain Angular Material-Tree

1 Answer

0 votes
by

The mat-tree provides the content design, style, tree that is used to display hierarchical data. The tree builds on the CDK tree's foundations and uses the same interface for its data source inputs and templates, except its element and attribute selectors will be prefixed with the material instead of CDs.

There are two types of trees: flat trees and nested trees.

Flat tree

In the flat tree, the hierarchy is flattened; nodes are inside each other, rather they are presented as siblings in sequence.

  1. <mat-tree>  
  2.   <mat-tree-node> parent node </mat-tree-node>  
  3.   <mat-tree-node> -- child node1 </mat-tree-node>  
  4.   <mat-tree-node> -- child node2 </mat-tree-node>  
  5. </mat-tree>  

app.component.html

  1. <mat-tree [dataSource]="dataSource" [treeControl]="treeControl">  
  2.   <mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding>  
  3.         <button mat-icon-button disabled></button>  
  4.     {{node.name}}  
  5.   </mat-tree-node>  
  6.   
  7.   <mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding>  
  8.     <button mat-icon-button matTreeNodeToggle  
  9.             [attr.aria-label]="'Toggle ' + node.name">  
  10.       <mat-icon class="mat-icon-rtl-mirror">  
  11.         {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}  
  12.       </mat-icon>  
  13.     </button>  
  14.     {{node.name}}  
  15.   </mat-tree-node>  
  16. </mat-tree>  

app.module.ts

  1. import {FlatTreeControl} from '@angular/cdk/tree';  
  2. import {Component} from '@angular/core';  
  3. import {MatTreeFlatDataSource, MatTreeFlattener} from '@angular/material/tree';  
  4. interface FoodNode {  
  5.   name: string;  
  6.   children?: FoodNode[];  
  7. }  
  8. const TREE_DATA: FoodNode[] = [  
  9.   {  
  10.     name: 'Fruit',  
  11.     children: [  
  12.       {name: 'Apple'},  
  13.       {name: 'Banana'},  
  14.       {name: 'Fruit loops'},  
  15.     ]  
  16.   }, {  
  17.     name: 'Vegetables',  
  18.     children: [  
  19.       {  
  20.         name: 'Green',  
  21.         children: [  
  22.           {name: 'Broccoli'},  
  23.           {name: 'Brussels sprouts'},  
  24.         ]  
  25.       }, {  
  26.         name: 'Orange',  
  27.         children: [  
  28.           {name: 'Pumpkins'},  
  29.           {name: 'Carrots'},  
  30.         ]  
  31.       },  
  32.     ]  
  33.   },  
  34. ];  
  35.   
  36. /** Flat node with expandable and level information */  
  37. interface ExampleFlatNode {  
  38.   expandable: boolean;  
  39.   name: string;  
  40.   level: number;  
  41. }  
  42.   
  43. /** 
  44.  * @title Tree with flat nodes 
  45.  */  
  46. @Component({  
  47.   selector: 'tree-flat-overview-example',  
  48.   templateUrl: 'tree-flat-overview-example.html',  
  49.   styleUrls: ['tree-flat-overview-example.css'],  
  50. })  
  51. export class TreeFlatOverviewExample {  
  52.   private _transformer = (node: FoodNode, level: number) => {  
  53.     return {  
  54.       expandable: !!node.children && node.children.length > 0,  
  55.       name: node.name,  
  56.       level: level,  
  57.     };  
  58.   }  
  59.   
  60.   treeControl = new FlatTreeControl<ExampleFlatNode>(  
  61.       node => node.level, node => node.expandable);  
  62.   
  63.   treeFlattener = new MatTreeFlattener(  
  64.       this._transformer, node => node.level, node => node.expandable, node => node.children);  
  65.   
  66.   dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);  
  67.   
  68.   constructor() {  
  69.     this.dataSource.data = TREE_DATA;  
  70.   }  
  71.   
  72.   hasChild = (_: number, node: ExampleFlatNode) => node.expandable;  
  73. }  

Output:

Angular Material-Tree
Angular Material-Tree

Flat trees are usually easy to style and observe. They are also more suited to scrolling variations, such as infinite or virtual scrolling.

Nested Tree

In the nested tree, children are placed inside their parent node in their DOM. The parent node has an outlet for all children to have a node.

  1. <mat-tree>  
  2.    <mat-nested-tree-node>  
  3.      parent node  
  4.      <mat-nested-tree-node> -- child node1 </mat-nested-tree-node>  
  5.      <mat-nested-tree-node> -- child node2 </mat-nested-tree-node>  
  6.    </mat-nested-tree-node>  
  7. </mat-tree>  

app.component.html

  1. <mat-tree [dataSource]="dataSource" [treeControl]="treeControl" class="example-tree">  
  2.   <!-- This is the tree node template for leaf nodes -->  
  3.   <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>  
  4.     <li class="mat-tree-node">  
  5.       <!-- use a disabled button to provide padding for tree leaf -->  
  6.       <button mat-icon-button disabled></button>  
  7.       {{node.name}}  
  8.     </li>  
  9.   </mat-tree-node>  
  10.   <!-- This is the tree node template for expandable nodes -->  
  11.   <mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild">  
  12.     <li>  
  13.       <div class="mat-tree-node">  
  14.         <button mat-icon-button matTreeNodeToggle  
  15.                 [attr.aria-label]="'Toggle ' + node.name">  
  16.           <mat-icon class="mat-icon-rtl-mirror">  
  17.             {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}  
  18.           </mat-icon>  
  19.         </button>  
  20.         {{node.name}}  
  21.       </div>  
  22.       <ul [class.example-tree-invisible]="!treeControl.isExpanded(node)">  
  23.         <ng-container matTreeNodeOutlet></ng-container>  
  24.       </ul>  
  25.     </li>  
  26.   </mat-nested-tree-node>  
  27. </mat-tree>  

app.component.ts

  1. import {NestedTreeControl} from '@angular/cdk/tree';  
  2. import {Component} from '@angular/core';  
  3. import {MatTreeNestedDataSource} from '@angular/material/tree';  
  4.   
  5. /** 
  6.  * Food data with nested structure. 
  7.  * Each node has a name and an optional list of children. 
  8.  */  
  9. interface FoodNode {  
  10.   name: string;  
  11.   children?: FoodNode[];  
  12. }  
  13.   
  14. const TREE_DATA: FoodNode[] = [  
  15.   {  
  16.     name: 'Fruit',  
  17.     children: [  
  18.       {name: 'Apple'},  
  19.       {name: 'Banana'},  
  20.       {name: 'Fruit loops'},  
  21.     ]  
  22.   }, {  
  23.     name: 'Vegetables',  
  24.     children: [  
  25.       {  
  26.         name: 'Green',  
  27.         children: [  
  28.           {name: 'Broccoli'},  
  29.           {name: 'Brussels sprouts'},  
  30.         ]  
  31.       }, {  
  32.         name: 'Orange',  
  33.         children: [  
  34.           {name: 'Pumpkins'},  
  35.           {name: 'Carrots'},  
  36.         ]  
  37.       },  
  38.     ]  
  39.   },  
  40. ];  
  41.   
  42. /** 
  43.  * @title Tree with nested nodes 
  44.  */  
  45. @Component({  
  46.   selector: 'tree-nested-overview-example',  
  47.   templateUrl: 'tree-nested-overview-example.html',  
  48.   styleUrls: ['tree-nested-overview-example.css'],  
  49. })  
  50. export class TreeNestedOverviewExample {  
  51.   treeControl = new NestedTreeControl<FoodNode>(node => node.children);  
  52.   dataSource = new MatTreeNestedDataSource<FoodNode>();  
  53.   
  54.   constructor() {  
  55.     this.dataSource.data = TREE_DATA;  
  56.   }  
  57.   
  58.   hasChild = (_: number, node: FoodNode) => !!node.children && node.children.length > 0;  
  59. }  

app.component.CSS

  1. .example-tree-invisible {  
  2.   display: none;  
  3. }  
  4.   
  5. .example-tree ul,  
  6. .example-tree li {  
  7.   margin-top: 0;  
  8.   margin-bottom: 0;  
  9.   list-style-type: none;  
  10. }  

Output:

Angular Material-Tree

Nested trees are easier to work with hierarchical relationships, which is difficult to accomplish with flat nodes.

Features

<mat-tree> itself relates to the rendering of only one tree structure. Additional features can be built above the tree by adding behavior inside the node template (e.g., padding and toggles). The table's data source will propagate interactions affecting intermittent data (such as expansion/collapse).

TreeControl

TreeControl controls the state of expansion/collapse of tree nodes. Users can recursively expand/collapse a tree node through tree control. For a nested tree node, the GetChildren function needs to be passed to NestedTreeControl to work smoothly. The getChildren function can return an overview of children for a given node or an array of children. FlatTreeControl needs to be passed for the flattened tree node to make the gatelevel and issandable functions recursive.

Toggle

To increase or collapse the tree node, a MatTreeNodeToggle will be added to the tree node. The toggle collapse serves the tree control and can extend the tree node by setting [matTreeNodeToggleRecursive] to correct.

Nested trees do not require padding as padding can be easily added to the structure of the DOM.

Accessibility

Trees without text or labels must be given a meaningful label via the area-label. Aria-read-only default to true if it is not set.

Mat-Tree does not manage any focus keyboard interactions on its own. Users can add desired keyboard interactions to their applications.

Related questions

0 votes
asked May 31, 2022 in Angular Material by Robin
0 votes
asked May 31, 2022 in Angular by Robin
...