Creating dynamic tree using MatTree in Angular

<h1>Welcome to tree component</h1>
<p>Welcome to tree child component</p>
import { TreeComponentComponent } from ‘./tree-component/tree-component.component’;
declarations: [AppComponent,TreeComponentComponent]
<h1>Welcome to tree component</h1><app-tree-component></app-tree-component>
import { MatSliderModule,MatButtonModule,MatTreeModule,MatIconModule } from ‘@angular/material’;
MatSliderModule,
MatButtonModule,
MatTreeModule,
MatIconModule
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
<!?-?This is the tree node template for leaf nodes ?
<mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding>
<!?-?use a disabled button to provide padding for tree leaf ?
<button mat-icon-button disabled></button>
{{node.name}}
</mat-tree-node>
<!?-?This is the tree node template for expandable nodes ?
<mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding>
<button mat-icon-button matTreeNodeToggle
[attr.aria-label]="'toggle ' + node.name">
<mat-icon class="mat-icon-rtl-mirror">
{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
</mat-icon>
</button>
{{node.name}}
</mat-tree-node>
</mat-tree>
import { Component, OnInit } from '@angular/core';
import {FlatTreeControl} from '@angular/cdk/tree';
import {MatTreeFlatDataSource, MatTreeFlattener} from '@angular/material/tree';
interface FoodNode {
name: string;
children?: FoodNode[];
}
const TREE_DATA: FoodNode[] = [
{
name: 'Fruit',
children: [ {name: 'Apple'}, {name: 'Banana'}, {name: 'Fruit loops'}, ]
},
{
name: 'Vegetables',
children: [ { name: 'Green',
children: [ {name: 'Broccoli'}, {name: 'Brussels sprouts'}, ]
},
{
name: 'Orange',
children: [ {name: 'Pumpkins'}, {name: 'Carrots'}, ] },
]
},
];
/** Flat node with expandable and level information */
interface ExampleFlatNode {
expandable: boolean;
name: string;
level: number;
}
@Component({
selector: 'app-tree-component',
templateUrl: './tree-component.component.html',
styleUrls: ['./tree-component.component.scss']
})
export class TreeComponentComponent implements OnInit {
private _transformer = (node: FoodNode, level: number) => {
return {
expandable: !!node.children && node.children.length > 0,
name: node.name,
level: level,
};
}
treeControl = new FlatTreeControl<ExampleFlatNode>(
node => node.level, node => node.expandable);
treeFlattener = new MatTreeFlattener(
this._transformer, node => node.level, node => node.expandable, node => node.children);
dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
constructor() {
//this.dataSource.data = TREE_DATA;
}
hasChild = (_: number, node: ExampleFlatNode) => node.expandable;
ngOnInit() {
this.dataSource.data = TREE_DATA;
}
}
const TREE_DATA: FoodNodeFlat[] = [
{ name: 'Fruit', Id: 1, parentId:null },
{ name: 'Apple', Id: 2, parentId: 1 },
{ name: 'Banana', Id: 3, parentId: 1 },
{ name: 'Fruit loops', Id: 4, parentId: 1 },
{ name: 'Vegetables', Id: 5, parentId:null },
{ name: 'Green', Id: 6, parentId: 5 },
{ name: 'Broccoli', Id: 7, parentId: 6 },
{ name: 'Brussels sprouts', Id: 8, parentId: 6 },
{ name: 'Orange', Id: 9, parentId: 5 },
{ name: 'Pumpkins', Id: 10, parentId: 9 },
{ name: 'Carrots', Id: 11, parentId: 9 },
{ name: 'India', Id: 12, parentId: null },
{ name: 'Maharashtra', Id: 13, parentId: 12 },
{ name: 'Mumbai', Id: 14, parentId: 13 },
{ name: 'Karnataka', Id: 15, parentId: 12 },
{ name: 'Bangalore', Id: 16, parentId: 15 },]
interface FoodNodeFlat {
name: string;
Id: Number;
parentId: Number;
children?: FoodNodeFlat[];
}
this.dataSource.data = TREE_DATA;
this.dataSource.data =this.treeConstruct(TREE_DATA);
//constructTree recursively iterates through the tree to create nested tree structure.
//We only need Id and parentId Columns in the flat data to construct this tree properly.
treeConstruct(treeData) {
let constructedTree = [];
for (let i of treeData) {
let treeObj = i;
let assigned = false;
this.constructTree(constructedTree, treeObj, assigned)
}
return constructedTree;
}
constructTree(constructedTree, treeObj, assigned) {if (treeObj.parentId == null) {
treeObj.children = [];
constructedTree.push(treeObj);
return true;
} else if (treeObj.parentId == constructedTree.Id) {
treeObj.children = [];
constructedTree.children.push(treeObj);
return true;
}
else {
if (constructedTree.children != undefined) {
for (let index = 0; index < constructedTree.children.length; index++) {
let constructedObj = constructedTree.children[index];
if (assigned == false) {
assigned = this.constructTree(constructedObj, treeObj, assigned);
}
}
} else {
for (let index = 0; index < constructedTree.length; index++) {
let constructedObj = constructedTree[index];
if (assigned == false) {
assigned = this.constructTree(constructedObj, treeObj, assigned);
}
}
}
return false;
}
}

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

ES6 Iterators and Generators — when are they actually useful?

How to mock window object in Jest with deep-rooted methods called

React Native — The Framework that Solved All My Needs for Building (and Released) an iOS & Android…

Top PWA Development Tools and Technologies For Your Business

Nullish coalescing operator (??) in JavaScript

Intro to JavaScript

Revise Your Stylesheets. Part 1. Color Scheme

Webpack explained simply — plugins, loaders and Babel

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Akshay Nayak

Akshay Nayak

More from Medium

Angular and Microfrontend Pipelines

Spring boot application & angular front-end

Dependency Injection in Angular

Explain Container and Nested Components in Angular

Explain Container and Nested Components in Angular