Angular Tree Structure using Angular Material Tree

Google launched the UI component toolkit known as Angular Material to enable Angular developers to create contemporary apps in a structured and responsive manner. By using this library, we can vastly improve the end-user experience and increase awareness of our application.

This library contains modern, ready-to-use items that need less than no further coding when used directly.

In Angular, trees are made with the mat-tree> directive. A form of structure that has data organized hierarchically is a tree. A node in the tree displays each set of data. The Component Dev Kit Tree was replaced with the Angular Material Tree, which is an enhancement (CDK-tree). A single data node can be expanded or collapsed into multiple data nodes using a Tree structure that is presented on the user interface (UI). A JSON object is used to dynamically build the tree. Trees come in two types:

  • Flat Tree
  • Nested Tree
  1. Install Angular Material using the below command
ng add @angular/material

2. Adding Mat-tree Component

– We need to import the Flat Tree component into our component file in order to use it:

import { FlatTreeControl } from '@angular/cdk/tree';

– We need to import the Nested Tree component into our component file in order to use it:

import { NestedTreeControl } from '@angular/cdk/tree';

– We need to import the Material Tree module into the app.module.ts file in order to use it:

import {MatTreeModule} from '@angular/material/tree';

Add the MatTreeModule to the NgModule imports array as well after using the import statement.

Flat Tree

A flat tree is a tree in which each node is sequentially presented on the DOM. The resulting tree features expandable/collapsible nodes, and DOM is reduced to a single-depth list.

Syntax :

<mat-tree>
    <mat-tree-node> Parent node name </mat-tree-node>
    <mat-tree-node> Child Node 1 </mat-tree-node>
    <mat-tree-node> Child Node 2 </mat-tree-node>
</mat-tree>

Project Structure: The project structure will look like this after successful installation

Add the Below code in flat-node-tree.component.ts

import { Component, OnInit } from "@angular/core";
import { FlatTreeControl } from "@angular/cdk/tree";
import { MatTreeFlatDataSource, MatTreeFlattener }from "@angular/material/tree";

interface Family {
 name: string;
 children?: Family[];
}

const FAMILY_TREE: Family[] = [
{
  name: "Joyce",
  children: [
  { name: "Mike" },
  { name: "Will" },
  { name: "Eleven", children: [{ name: "Hopper" }] },
  { name: "Lucas" },
  { name: "Dustin", children: [{ name: "Winona" }] },
  ],
},
{
  name: "Jean",
  children: [{ name: "Otis" }, { name: "Maeve" }],
},
];

/** Flat node with expandable and level information */
interface ExampleFlatNode {
expandable: boolean;
  name: string;
  level: number;
}

@Component({
  selector: "app-flat-node-tree",
  templateUrl: "./flat-node-tree.component.html",
  styleUrls: ["./flat-node-tree.component.css"],
})

export class FlatNodeTreeComponent implements OnInit {
private _transformer = (node: Family, 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 = FAMILY_TREE;
}

hasChild = (_: number,
  node: ExampleFlatNode) => node.expandable;

ngOnInit(): void {}
}

Add the Below code in flat-node-tree.component.html

<h1>The Code Hubs</h1>
<h3>MatTree Example</h3>
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
     <mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding>	
          <!-- Adding a disabled property to the button so as to give padding to nodes -->
          <button mat-icon-button disabled></button>
      {{node.name}}
     </mat-tree-node>
  
     <!-- 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>

Add the Below code in flat-node-tree.component.css

h1, h3 {
color: green;
font-family: "Roboto", sans-serif;
text-align: center;
}

.mat-tree {
background: transparent;
}

.mat-tree-node {
color: black;
}

Add it into app.component.html

<app-flat-node-tree></app-flat-node-tree>

Add it into app.module.ts 

import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app.component";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { FlatNodeTreeComponent } from "./flat-node-tree/flat-node-tree.component";
import { MatTreeModule } from "@angular/material/tree";
import { MatIconModule } from "@angular/material/icon";

@NgModule({
  declarations: [AppComponent, FlatNodeTreeComponent],
  exports: [AppComponent],
  imports: [
  CommonModule,
  BrowserAnimationsModule,
  BrowserModule,
  MatTreeModule,
  MatIconModule,
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

Nested Tree

In DOM, a nested tree is one in which all of the child nodes are placed inside their parent node. When we have a difficult relationship between nodes and a flat tree is incapable of providing the structure necessary, we should use nested trees. Each parent has its own output via which the child nodes are specified.

Syntax:

<mat-tree>
 <mat-nested-tree-node>
   Parent node name
   <mat-nested-tree-node> Child Node 1 </mat-nested-tree-node>
   <mat-nested-tree-node> Child Node 2 </mat-nested-tree-node>
   .
   .
   .
   <mat-nested-tree-node> Child Node N </mat-nested-tree-node>
 </mat-nested-tree-node>
</mat-tree>

Project Structure: After successful installation, the project structure will look like the following image:

…….

Add the Below code in nested-tree-example.component.ts

import { Component, OnInit } from "@angular/core";
import { NestedTreeControl } from "@angular/cdk/tree";
import { MatTreeNestedDataSource } from "@angular/material/tree";

interface Smartphone {
   parent_company: string;
   sub_brand?: Smartphone[];
}

const TREE_DATA: Smartphone[] = [
{
  parent_company: "Xiaomi",
  sub_brand: [
     { parent_company: "Poco" },
     { parent_company: "Redmi" },
     { parent_company: "Mijia" },
  ],
},
{
  parent_company: "BBK Electronics",
  sub_brand: [
  {
    parent_company: "Vivo",
    sub_brand: [{ parent_company: "iQoo" }],
  },
  {
    parent_company: "Oppo",
    sub_brand: [{ parent_company: "Realme" },
          { parent_company: "Dizo" }],
  },
  ],
},
];

  @Component({
     selector: "app-nested-tree-example",
     templateUrl: "./nested-tree-example.component.html",
     styleUrls: ["./nested-tree-example.component.css"],
  })
  export class NestedTreeExampleComponent implements OnInit {
  treeControl = new NestedTreeControl<Smartphone>((node) => node.sub_brand);
  dataSource = new MatTreeNestedDataSource<Smartphone>();
  constructor() {
  this.dataSource.data = TREE_DATA;
  }
  hasChild = (_: number, node: Smartphone) => !!node.sub_brand && node.sub_brand.length > 0;

  ngOnInit(): void {}
}

Add the Below code in nested-tree-example.component.html

<h1>The Code Hubs</h1>
<h3>Nested Tree Example</h3>
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl"	class="example-tree">
  <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
    {{node.parent_company}}
  </mat-tree-node>
  <mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild">
    <div class="mat-tree-node">
      <button mat-icon-button matTreeNodeToggle [attr.aria-label]="'Toggle ' + node.parent_company">
        <mat-icon class="mat-icon-rtl-mirror">
          {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
        </mat-icon>
      </button>
      {{node.parent_company}}
    </div>
    <div [class.example-tree-invisible]="!treeControl.isExpanded(node)" role="group">
      <ng-container matTreeNodeOutlet></ng-container>
    </div>
  </mat-nested-tree-node>
</mat-tree>

Add the Below code in nested-tree-example.component.css

.example-tree-invisible {
   display: none;
}

.example-tree ul,.example-tree li {
   margin-top: 0;
   margin-bottom: 0;
   list-style-type: none;
}

/* This padding sets the alignment of the nested nodes. */
.example-tree .mat-nested-tree-node div[role="group"] {
   padding-left: 40px;
}

.example-tree div[role="group"] > .mat-tree-node {
    padding-left: 40px;
}

h1,h3 {
    color: green;
    font-family: "Roboto", sans-serif;
    text-align: left;
}

.mat-tree {
    background: transparent;
}

.mat-tree-node {
    color: black;
}

Add it in  app.component.cshtml

<app-nested-tree-example> </app-nested-tree-example>

Add it in app.module.ts

import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app.component";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { NestedTreeExampleComponent } from "./nested-tree-example/nested-tree-example.component";
import { MatTreeModule } from "@angular/material/tree";
import { MatIconModule } from "@angular/material/icon";

@NgModule({
    declarations: [AppComponent, NestedTreeExampleComponent],
    exports: [AppComponent],
    imports: [
  CommonModule,
  BrowserAnimationsModule,
  BrowserModule,
  MatTreeModule,
  MatIconModule,
    ],
    bootstrap: [AppComponent],
})
export class AppModule {}

Submit a Comment

Your email address will not be published.

Subscribe

Select Categories