Hierarchical tree layout in Angular Diagram control

23 Aug 20259 minutes to read

The hierarchical tree layout arranges nodes in a tree-like structure where nodes can have multiple parent nodes, creating complex organizational relationships. Unlike traditional tree structures with single parent-child relationships, this layout supports scenarios such as matrix organizations, project dependencies, or any structure where entities report to multiple authorities. The layout automatically determines positioning without requiring a specified root node.

Hierarchical tree layout with nodes and connectors

To arrange nodes in a hierarchical structure, specify the layout type as HierarchicalTree. This approach provides full control over node and connector definitions while leveraging automatic positioning.

import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, NodeModel, ConnectorModel, LayoutModel, DiagramModule,
  HierarchicalTreeService, HierarchicalTree } from '@syncfusion/ej2-angular-diagrams';

Diagram.Inject(HierarchicalTree);

@Component({
  imports: [ DiagramModule ],

  providers: [HierarchicalTreeService],
  standalone: true,
  selector: "app-container",
  template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" [nodes]="nodes" [connectors]="connectors"
  [getNodeDefaults]="getNodeDefaults" [getConnectorDefaults]="getConnectorDefaults" [layout]="layout"> </ejs-diagram>`,
  encapsulation: ViewEncapsulation.None
})
export class AppComponent {
  @ViewChild("diagram")
  public diagram?: DiagramComponent;
  public layout?: LayoutModel;

  //Initialize nodes for diagram
  public nodes: NodeModel[] = [
    {
      id: 'Steve-Ceo',
    },
    {
      id: 'Kevin-Manager',
    },
    {
      id: 'Peter-Manager',
    },
    {
      id: 'John-Manager',
    },
    {
      id: 'Mary-CSE',
    },
    {
      id: 'Jim-CSE',
    },
    {
      id: 'Martin-CSE',
    },
  ];

  //Initialize connectors for diagram
  public connectors: ConnectorModel[] = [
    {
      id: 'Steve-Ceo_Kevin-Manager',
      sourceID: 'Steve-Ceo',
      targetID: 'Kevin-Manager',
    },
    {
      id: 'Steve-Ceo_Peter-Manager',
      sourceID: 'Steve-Ceo',
      targetID: 'Peter-Manager',
    },
    {
      id: 'Peter-Manager_John-Manager',
      sourceID: 'Peter-Manager',
      targetID: 'John-Manager',
    },
    {
      id: 'Peter-Manager_Mary-CSE',
      sourceID: 'Peter-Manager',
      targetID: 'Mary-CSE',
    },
    {
      id: 'Kevin-Manager_Jim-CSE',
      sourceID: 'Kevin-Manager',
      targetID: 'Jim-CSE',
    },
    {
      id: 'Kevin-Manager_Martin-CSE',
      sourceID: 'Kevin-Manager',
      targetID: 'Martin-CSE',
    },
  ];

  //Sets the default properties for all the Nodes
  public getNodeDefaults(node: NodeModel): NodeModel {
    node.annotations = [{ content: node.id }];
    node.width = 100; node.height = 40;
    return node;
  }

  //Sets the default properties for all the connectors
  public getConnectorDefaults(connector: ConnectorModel): ConnectorModel {
    connector.type = 'Orthogonal';
    return connector;
  }
  ngOnInit(): void {
    //Uses layout to auto-arrange nodes on the Diagram page
    this.layout = {
      //Sets layout type
      type: 'HierarchicalTree'
    }
  }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

NOTE

The HierarchicalTree module must be injected into the diagram to use hierarchical tree layout functionality.

Hierarchical layout with DataSource

For data-driven scenarios, hierarchical layout can be created using a DataSource, which automatically generates nodes and connectors based on the data relationships. This approach is more efficient for large datasets and dynamic content.

import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, NodeModel, ConnectorModel, LayoutModel, DataSourceModel, DiagramModule,
  HierarchicalTreeService, DataBindingService, DataBinding, HierarchicalTree } from '@syncfusion/ej2-angular-diagrams';
import { DataManager, Query } from '@syncfusion/ej2-data';

Diagram.Inject(DataBinding, HierarchicalTree);

@Component({
  imports: [ DiagramModule ],

  providers: [HierarchicalTreeService, DataBindingService],
  standalone: true,
  selector: "app-container",
  template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" [getNodeDefaults]="getNodeDefaults"
    [getConnectorDefaults]="getConnectorDefaults" [layout]="layout" [dataSourceSettings]="dataSourceSettings">
    </ejs-diagram>`,
  encapsulation: ViewEncapsulation.None
})

export class AppComponent {
  @ViewChild("diagram")
  public diagram?: DiagramComponent;
  public items?: DataManager;
  public layout?: LayoutModel;
  public dataSourceSettings?: DataSourceModel;

  //Initializes data source
  public data: object[] = [
    {
      Name: "Steve-Ceo"
    },
    {
      Name: "Kevin-Manager",
      ReportingPerson: "Steve-Ceo"
    },
    {
      Name: "Peter-Manager",
      ReportingPerson: "Steve-Ceo"
    },
    {
      Name: "John- Manager",
      ReportingPerson: "Peter-Manager"
    },
    {
      Name: "Mary-CSE ",
      ReportingPerson: "Peter-Manager"
    },
    {
      Name: "Jim-CSE ",
      ReportingPerson: "Kevin-Manager"
    },
    {
      Name: "Martin-CSE",
      ReportingPerson: "Kevin-Manager"
    }
  ];

  //Sets the default properties for all the Nodes
  public getNodeDefaults(node: NodeModel): NodeModel {
    node.annotations = [{ content: (node.data as { Name: 'string' }).Name }];
    node.width = 100; node.height = 40;
    return node;
  }

  //Sets the default properties for all the connectors
  public getConnectorDefaults(connector: ConnectorModel): ConnectorModel {
    connector.type = 'Orthogonal';
    return connector;
  }

  ngOnInit(): void {
    this.items = new DataManager(this.data as JSON[], new Query().take(7));

    //Uses layout to auto-arrange nodes on the Diagram page
    this.layout = {
      //Sets layout type
      type: 'HierarchicalTree'
    }

    //Configures data source for Diagram
    this.dataSourceSettings = {
      id: 'Name',
      parentId: 'ReportingPerson',
      dataSource: this.items
    }
  }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

NOTE

When using DataSource for layout generation, both DataBinding and HierarchicalTree modules must be injected into the diagram.
Hierarchical tree layout showing nodes with multiple parent relationships