How to Create Angular Tree View Component

How to Create Angular Tree View Component

In this tutorial, I will teach you how to create an angular tree view component that loops over a JSON recursively as long as there’s a “children” property. The angular tree component which we are going to create now is a reusable component.

angular tree component tutorial
Angular Tree Component

Steps to Create Angular Tree Component

  1. Create a Tree component.
  2. Create a Dummy JSON Model for the tree.
  3. Receive Input from other components.
  4. Create the Tree Template
  5. Add Expand/Collapse option
  6. Add Styles to the Tree

Create a Tree Component

Use the following command in your terminal/cmd to create the Tree component, you can rename it as per your need.

ng generate component tree

The @angular/cli will generate three files for the component:

  1. tree.component.html – This is the template HTML of our tree component.
  2. tree.component.ts – This is where our component metadata and controller class will be written.
  3. tree.component.css – A component-specific style sheet file.

Create a Mock Data Model File

For brevity, we are making a mock data as JSON in a model file instead of calling an API service. Create a new file in the tree component folder, sampledata.model.ts. Copy and paste the below code into the model file.

export class SampleData {
    data = [{
        name: "Sample App One",
        children: [{
            name: "Business One",
            children: [{
                name: "Branch One",
                children: [{
                    name: "Sub Branch One",
                    children: []
                }, {
                    name: "Sub Branch Two",
                    children: []
                }]
            }, {
                name: "Branch Two",
                children: [{
                    name: "Sub Branch One",
                    children: []
                }, {
                    name: "Sub Branch Two",
                    children: []
                }]
            }]
        }, {
            name: "Business Two",
            children: [{
                name: "Branch One",
                children: []
            }, {
                name: "Branch Two",
                children: []
            }]
        }]
    },
    {
        name: "Sample App Two",
        children: [{
            name: "Business One",
            children: [{
                name: "Branch One",
                children: []
            }, {
                name: "Branch Two",
                children: []
            }]
        }, {
            name: "Business Two",
            children: [{
                name: "Branch One",
                children: []
            }, {
                name: "Branch Two",
                children: []
            }]
        }]
    }, {
        name: "Sample App Three",
        children: [{
            name: "Business One",
            children: [{
                name: "Branch One",
                children: []
            }, {
                name: "Branch Two",
                children: []
            }]
        }, {
            name: "Business Two",
            children: [{
                name: "Branch One",
                children: []
            }, {
                name: "Branch Two",
                children: []
            }]
        }]
    }];
}

Receive Data from Other Components

To make our angular tree reusable, it should receive the data from other components. The angular’s @Input() decorator is used to receive the data from other components. Change your tree.component.ts as follows

import { Component, OnInit, Input } from "@angular/core";

@Component({
  selector: 'app-tree',
  templateUrl: './tree.component.html',
  styleUrls: ['./tree.component.scss'],
})

export class TreeComponent implements OnInit {
  @Input() items; //data receive from other components
  
  constructor() { } 

  ngOnInit() { }
  
}

At the import statement, we should import the angular Input. Then only we can receive the data by making use of @Input() decorator. In our case, we have a items variable as a @Input() decorator.

Create the Angular Tree Template

The tree template is where all the dynamism is added to make it recursive.

<ul class="tree-view">
  <li class="system-main" 
     *ngFor="let item of items">
    <div class="system-main__apps" (click)="onexpand(item)">
        <span class="system-main__icon"><i class="fa fa-folder"></i></span>
        <span class="system-main__name" > {{ item.name }} </span>
    </div>
    <ul *ngIf="item.children && item.expanded">
      <app-tree  [items]="item.children"></app-tree>
    </ul>
  </li>
</ul>
  • Firstly, we loop over the items property using *ngFor directive of Angular.
  • We print the name of the item using angular template expression {{ item.name }}.

How to Create Recursive Loop in Angular Template

//...
//Inside the *ngFor..

<ul *ngIf="item.children">
      <app-tree  [items]="item.children"></app-tree> //This is where the recursive template call has been made
</ul>

//......

Inside the *ngFor loop, we call this component selector <app-tree> again with the input property [items]='item.children'. The item.children is the children property of the current item. This will recursively loop through the JSON as long as there’s a children property for the current item.

Learn How to Recursively Search JSON/Object in Angular using Angular Pipe

Expand and Collapse option in Angular Tree:

To toggle the tree, we should create a method in our tree.component.ts

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-treeview',
  templateUrl: './treeview.component.html',
  styleUrls: ['./treeview.component.scss'],
})


export class TreeviewComponent implements OnInit {
  @Input() items;

  constructor() { }

  ngOnInit() {
  }

  onexpand(item) {
    if (item.expanded) {
      item.expanded = !item.expanded;
      return;
    } else {
      if (item.children) {
        if (item.children.length > 0) {
          item.expanded = true;
        } else {
          item.expanded = false;
        }
      }
    }
  }


}

The onExpand method will be invoked when the user clicks the <li> item, this method receives the object of the clicked item. Based on the expanded property of the object, it will expand or collapse the child tree.

Add Styles for the Angular Tree

* {
  box-sizing: border-box;
}

.system-container {
    position: relative;
    height: 100vh;
    overflow: auto; }
  
  .systems {
    width: 60rem;
    margin: 0 auto 50px auto; }
    .systems__apps {
      background: #0981b1;
      color: #fff;
      padding: 8px;
      font-size: 16px;
      margin: 6px;
      border-radius: 3px;
      cursor: pointer;
      transition: all .3s ease-in-out;
    }
  
      .systems__apps:hover {
        background: #026086;
    }
    
    .systems__icon {
      font-size: 20px;
      margin: 0 10px; }
    .systems__expands {
      float: right;
      margin-top: 5px; }
    .systems__search {
      padding-left: 40px; }
  
  .systems-header .header-primary {
    margin-left: 180px; }
  
  .system-main {
   }
    .system-main__apps {
      background: #0981b1;
      color: #fff;
      padding: 14px;
      font-size: 16px;
      margin: 10px 0;
      border-radius: 3px;
      transition: all .3s ease;
      backface-visibility: hidden; }
      .system-main__apps:hover {
        background: #5f1aff;
        cursor: pointer; }
    .system-main__icon {
      font-size: 20px;
      margin-right: 10px;
      margin-left: 20px; }
    .system-main__expands {
      float: right;
      margin-top: 5px; }
  
  .system-child {
    /*OLD CHILD APPS STYLE */ }
    .system-child__apps {
      color: #000;
      padding: 8px;
      font-size: 16px;
      margin: 4px 12px;
      border-bottom: 1px solid white;
      transition: all .2s ease;
      backface-visibility: hidden; }
      .system-child__apps:hover {
        color: #0981b1;
        cursor: pointer;
        transform: scale(1.01); }
    .system-child__icon {
      font-size: 20px;
      margin-right: 10px;
      margin-left: 20px;
      color: #0981b1; }
    .system-child__expands {
      float: right;
      margin-top: 5px;
      color: #4d4d4d; }

      .systems__go {
        text-align: right;
        display: inline-block;
        float: right;
        font-size: 20px;
        color: #ffe942;
        transition: all .2s;
        margin-right: 12px;
        text-shadow: 2px 2px 1rem #383838;
    }

    .systems__go:hover {
        transform: translateX(5px);
    }
  
  @media only screen and (max-width: 985px) {
    .systems {
      width: 100%; } }
  
      .tree-view {
        list-style-type: none;
        transition: all .3s ease-in-out;
      }

Just copy and paste the above CSS to your tree.component.css file to style our tree component.

Using the Angular Tree Component

Now, the angular tree component is ready, we should use it in our other components. In this tutorial, i am going to use our tree in my app component

1. Import Sample Data in app.component.ts

import { Component } from '@angular/core';
import { SampleData }  from './sampledata.model'; //import the sample data class
@Component({
  selector: 'bn-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  sampleData = new SampleData().data; // add the data to a property
}

2. Use the app-tree in app.component.ts

<app-tree [items]="sampleData"></app-tree>

The sampleData is the input for our tree.

3. Run ng serve

Open command prompt and run ng serve - o, that’s it you can see the created tree in browser

Conclusion

This is a pretty straight forward tutorial on how to create a simple angular tree component using a JSON. It taught you the recursive loop in templates which is a key to create a tree.

In the real world, you might have a tree component that has multiple options like search, selected item of a tree, checkbox, themes, etc. In that case, you can use the BN NG Tree npm which is a very stylish tree component for Angular.