Complex hierarchical tree layout in EJ2 TypeScript Diagram control

16 Dec 202424 minutes to read

Complex hierarchical tree layout arranges nodes in a tree-like structure, where the child node can have more than one parent. This layout is an extended version of the hierarchical tree layout. To create a complex hierarchical tree, the type property of layout should be set as ComplexHierarchicalTree.

Complex hierarchical tree layout with nodes and connectors

The following example demonstrates how to render a complex hierarchical tree layout using nodes and connectors. To achieve this, you need to define the nodes and connectors collections and assign them to the diagram. Additionally, you need to set the layout type to ComplexHierarchicalTree.

import {
    Diagram,
    ConnectorModel,
    NodeModel,
    ComplexHierarchicalTree,
    TextModel,
  } from '@syncfusion/ej2-diagrams';
  Diagram.Inject(ComplexHierarchicalTree);
  //Initializes nodes
  let nodes: NodeModel[] = [
    { id: 'node1' },
    { id: 'node2' },
    { id: 'node3' },
    { id: 'node4' },
    { id: 'node5' },
    { id: 'node6' },
    { id: 'node7' },
  ];
  //Initialize connectors
  let connectors: ConnectorModel[] = [
    { id: 'node1-node4', sourceID: 'node1', targetID: 'node4' },
    { id: 'node2-node4', sourceID: 'node2', targetID: 'node4' },
    { id: 'node3-node4', sourceID: 'node3', targetID: 'node4' },
    { id: 'node4-node5', sourceID: 'node4', targetID: 'node5' },
    { id: 'node4-node6', sourceID: 'node4', targetID: 'node6' },
    { id: 'node5-node6', sourceID: 'node6', targetID: 'node7' },
  ];
  let diagram: Diagram = new Diagram({
    width: '100%',
    height: 1000,
    nodes: nodes,
    connectors: connectors,
    //Uses layout to auto-arrange nodes on the diagram page
    layout: {
      //Sets layout type
      type: 'ComplexHierarchicalTree',
      orientation: 'TopToBottom',
      horizontalAlignment: 'Center',
      verticalAlignment: 'Top',
    },
    //Sets the default properties for nodes and connectors
    getNodeDefaults: (obj: NodeModel) => {
      (obj.width = 70),
        (obj.height = 70),
        (obj.annotations = [{ content: obj.id }]);
      obj.style = {
        fill: '#6BA5D7',
        strokeColor: 'none',
        strokeWidth: 2,
      };
      obj.borderColor = 'white';
      obj.backgroundColor = '#6BA5D7';
      obj.borderWidth = 1;
      (obj.shape as TextModel).margin = {
        left: 5,
        right: 5,
        top: 5,
        bottom: 5,
      };
      return obj;
    },
    getConnectorDefaults: (connector: ConnectorModel, diagram: Diagram) => {
      connector.style = {
        strokeColor: '#6BA5D7',
        strokeWidth: 2,
      };
      connector.targetDecorator.style.fill = '#6BA5D7';
      connector.targetDecorator.style.strokeColor = '#6BA5D7';
      connector.type = 'Orthogonal';
      return connector;
    },
  });
  diagram.appendTo('#element');
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Diagram</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-diagrams/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-navigations/styles/fabric.css" rel="stylesheet" />
    <script src="systemjs.config.js"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id='element'></div>
    </div>
</body>

</html>

Complex hierarchical tree layout with DataSource

The following code example illustrates how to create a complex hierarchical tree with DataSource.

import { DataManager, Query } from '@syncfusion/ej2-data';
import {
  Diagram,
  ConnectorModel,
  NodeModel,
  ComplexHierarchicalTree,
  TextModel,
  DataBinding,
} from '@syncfusion/ej2-diagrams';
Diagram.Inject(ComplexHierarchicalTree, DataBinding);
//Initializes dataSource
let data: object[] = [
  {
    Name: 'node11',
    fillColor: '#e7704c',
    border: '#c15433',
    ReportingPerson: null,
  },
  {
    Name: 'node12',
    ReportingPerson: ['node114'],
    fillColor: '#efd46e',
    border: '#d6b123',
  },
  {
    Name: 'node13',
    ReportingPerson: ['node12'],
    fillColor: '#58b087',
    border: '#16955e',
  },
  {
    Name: 'node14',
    ReportingPerson: ['node12'],
    fillColor: '#58b087',
    border: '#16955e',
  },
  {
    Name: 'node15',
    ReportingPerson: ['node12'],
    fillColor: '#58b087',
    border: '#16955e',
  },
  {
    Name: 'node116',
    ReportingPerson: ['node22', 'node12'],
    fillColor: '#58b087',
    border: '#16955e',
  },
  { Name: 'node16', ReportingPerson: [], fillColor: '#14ad85' },
  {
    Name: 'node17',
    ReportingPerson: ['node13', 'node14', 'node15'],
    fillColor: '#659be5',
    border: '#3a6eb5',
  },
  { Name: 'node18', ReportingPerson: [], fillColor: '#14ad85' },
  {
    Name: 'node19',
    ReportingPerson: ['node16', 'node17', 'node18'],
    fillColor: '#8dbe6c',
    border: '#489911',
  },
  {
    Name: 'node110',
    ReportingPerson: ['node16', 'node17', 'node18'],
    fillColor: '#8dbe6c',
    border: '#489911',
  },
  {
    Name: 'node111',
    ReportingPerson: ['node16', 'node17', 'node18', 'node116'],
    fillColor: '#8dbe6c',
    border: '#489911',
  },
  { Name: 'node21', fillColor: '#e7704c', border: '#c15433' },
  {
    Name: 'node22',
    ReportingPerson: ['node114'],
    fillColor: '#efd46e',
    border: '#d6b123',
  },
  {
    Name: 'node23',
    ReportingPerson: ['node22'],
    fillColor: '#58b087',
    border: '#16955e',
  },
  {
    Name: 'node24',
    ReportingPerson: ['node22'],
    fillColor: '#58b087',
    border: '#16955e',
  },
  {
    Name: 'node25',
    ReportingPerson: ['node22'],
    fillColor: '#58b087',
    border: '#16955e',
  },
  { Name: 'node26', ReportingPerson: [], fillColor: '#14ad85' },
  {
    Name: 'node27',
    ReportingPerson: ['node23', 'node24', 'node25'],
    fillColor: '#659be5',
    border: '#3a6eb5',
  },
  { Name: 'node28', ReportingPerson: [], fillColor: '#14ad85' },
  {
    Name: 'node29',
    ReportingPerson: ['node26', 'node27', 'node28', 'node116'],
    fillColor: '#8dbe6c',
    border: '#489911',
  },
  {
    Name: 'node210',
    ReportingPerson: ['node26', 'node27', 'node28'],
    fillColor: '#8dbe6c',
    border: '#489911',
  },
  {
    Name: 'node211',
    ReportingPerson: ['node26', 'node27', 'node28'],
    fillColor: '#8dbe6c',
    border: '#489911',
  },
  { Name: 'node31', fillColor: '#e7704c', border: '#c15433' },
  {
    Name: 'node114',
    ReportingPerson: ['node11', 'node21', 'node31'],
    fillColor: '#f3904a',
    border: '#d3722e',
  },
];

let items: DataManager = new DataManager(data as JSON[], new Query().take(7));

let diagram: Diagram = new Diagram({
  width: '100%',
  height: 1000,
  dataSourceSettings: {
    id: 'Name',
    parentId: 'ReportingPerson',
    dataSource: items,
  },
  //Uses layout to auto-arrange nodes on the diagram page
  layout: {
    //Sets layout type
    type: 'ComplexHierarchicalTree',
    orientation: 'TopToBottom',
    horizontalAlignment: 'Center',
    verticalAlignment: 'Top',
    horizontalSpacing: 50,
    verticalSpacing: 50,
  },
  //Sets the default properties for nodes and connectors
  getNodeDefaults: (obj: NodeModel) => {
    (obj.width = 70),
      (obj.height = 70),
      (obj.style = {
        fill: '#6BA5D7',
        strokeColor: 'none',
        strokeWidth: 2,
      });
    obj.borderColor = 'white';
    obj.backgroundColor = '#6BA5D7';
    obj.borderWidth = 1;
    (obj.shape as TextModel).margin = {
      left: 5,
      right: 5,
      top: 5,
      bottom: 5,
    };
    return obj;
  },
  getConnectorDefaults: (connector: ConnectorModel, diagram: Diagram) => {
    connector.style = {
      strokeColor: '#6BA5D7',
      strokeWidth: 2,
    };
    connector.targetDecorator.style.fill = '#6BA5D7';
    connector.targetDecorator.style.strokeColor = '#6BA5D7';
    connector.type = 'Orthogonal';
    return connector;
  },
});
diagram.appendTo('#element');
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Diagram</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-diagrams/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-navigations/styles/fabric.css" rel="stylesheet" />
    <script src="systemjs.config.js"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id='element'></div>
    </div>
</body>

</html>

Complex hierarchical tree layout

NOTE

In Diagram Layouts, all root nodes will always render at the same level. This default behavior cannot be changed to render different trees at distinct levels.

Line Distribution

Line distribution is used to arrange the connectors without overlapping in automatic layout. In some cases, the automatic layout connectors connecting to the nodes will be overlapped with one another. So user can decide whether the segment of each connector from a single parent node should be same point or different point. The connectionPointOrigin property of layout is used to enable or disable the line distribution in layout. By default ConnectionPointOrigin will be SamePoint.

The following code example illustrates how to create a complex hierarchical tree with line distribution.

import {
    Diagram, ConnectorModel, NodeModel, DiagramConstraints,ConnectionPointOrigin,LineDistribution, ComplexHierarchicalTree, DataBinding
} from '@syncfusion/ej2-diagrams';
import { DataManager, Query } from '@syncfusion/ej2-data';
Diagram.Inject(DataBinding, ComplexHierarchicalTree, LineDistribution);
//Initializes data source
let Data: object[] =  [
        { "Name": "node11" },
        { "Name": "node12", "ReportingPerson": ["node114"] },
        { "Name": "node13", "ReportingPerson": ["node12"] },
        { "Name": "node14", "ReportingPerson": ["node12"] },
        { "Name": "node15", "ReportingPerson": ["node12"] },
        { "Name": "node116", "ReportingPerson": ["node22","node12"] },
        { "Name": "node16", "ReportingPerson": [] },
        { "Name": "node18", "ReportingPerson": [] },
        { "Name": "node21" },
        { "Name": "node22", "ReportingPerson": ["node114"] },
        { "Name": "node23", "ReportingPerson": ["node22"] },
        { "Name": "node24", "ReportingPerson": ["node22"] },
        { "Name": "node25", "ReportingPerson": ["node22"] },
        { "Name": "node26", "ReportingPerson": [] },
        { "Name": "node28", "ReportingPerson": [] },
        { "Name": "node31" },
        { "Name": "node114", "ReportingPerson": ["node11", "node21", "node31"]}
    ];
let items: DataManager = new DataManager(Data as JSON[], new Query().take(25));
// Initializes the diagram
let diagram: Diagram = new Diagram({
    width: '100%', height: '590px',
    layout: {
        type: 'ComplexHierarchicalTree',
        connectionPointOrigin: ConnectionPointOrigin.DifferentPoint,
        horizontalSpacing: 40, verticalSpacing: 40, horizontalAlignment: "Left", verticalAlignment: "Top",
        margin: { left: 0, right: 0, top: 0, bottom: 0 },
        orientation: 'TopToBottom'
    },
    getNodeDefaults: (obj: NodeModel) => {
        obj.width = 40; obj.height = 40;
        obj.shape = { type: 'Basic', shape: 'Rectangle' };
        obj.style = { fill: '#6BA5D7', strokeColor: 'none', strokeWidth: 2 };
        obj.borderWidth = 1;
        obj.backgroundColor = '#6BA5D7';
        return obj;
    },
    getConnectorDefaults: (connector: ConnectorModel, diagram: Diagram) => {
        connector.type = 'Orthogonal';
        connector.cornerRadius = 7;
        connector.targetDecorator.height = 7;
        connector.targetDecorator.width = 7;
        connector.style = { strokeColor: '#6BA5D7', strokeWidth: 1 };
        connector.targetDecorator.style.fill  =  '#6BA5D7';
        connector.targetDecorator.style.strokeColor  =  '#6BA5D7';
        return connector;
    },
    dataSourceSettings: { id: 'Name', parentId: 'ReportingPerson', dataSource: items },
    snapSettings: { constraints: 0 }
});
diagram.appendTo('#element');
diagram.fitToPage({ mode: 'Width' });
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Diagram</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-diagrams/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-navigations/styles/fabric.css" rel="stylesheet" />
    <script src="systemjs.config.js"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id='element'></div>
    </div>
</body>

</html>

NOTE

If you want to use line distribution in diagram layout, you need to inject LineDistribution module in the diagram.

Different point

Linear Arrangement

Linear arrangement is used to linearly arrange the child nodes in layout, which means the parent node is placed in the center corresponding to its children. When line distribution is enabled, linear arrangement is also activated by default. The arrangement property of layout is used to enable or disable the linear arrangement in layout. By default arrangement will be Nonlinear.

NOTE

If you want to use linear arrangement in diagram layout, you need to inject LineDistribution module in the diagram. Linear arrangement is applicable only for complex hierarchical tree layout.

The following code illustrates how to allow a linear arrangement in diagram layout.

import {
  Diagram,
  ConnectorModel,
  NodeModel,
  ConnectionPointOrigin,
  LineDistribution,
  ComplexHierarchicalTree,
  DataBinding,
  ChildArrangement,
} from '@syncfusion/ej2-diagrams';
import { DataManager, Query } from '@syncfusion/ej2-data';
Diagram.Inject(DataBinding, ComplexHierarchicalTree, LineDistribution);
//Initializes data source
let Data: object[] = [
  { Name: 'node11' },
  { Name: 'node12', ReportingPerson: ['node114'] },
  { Name: 'node13', ReportingPerson: ['node12'] },
  { Name: 'node14', ReportingPerson: ['node12'] },
  { Name: 'node15', ReportingPerson: ['node12'] },
  { Name: 'node116', ReportingPerson: ['node22', 'node12'] },
  { Name: 'node18', ReportingPerson: [] },
  { Name: 'node21' },
  { Name: 'node22', ReportingPerson: ['node114'] },
  { Name: 'node23', ReportingPerson: ['node22'] },
  { Name: 'node24', ReportingPerson: ['node22'] },
  { Name: 'node25', ReportingPerson: ['node22'] },
  { Name: 'node26', ReportingPerson: [] },
  { Name: 'node28', ReportingPerson: [] },
  { Name: 'node31' },
  { Name: 'node114', ReportingPerson: ['node11', 'node21', 'node31'] },
];
let items: DataManager = new DataManager(Data as JSON[], new Query().take(25));
// Initializes the diagram
let diagram: Diagram = new Diagram({
  width: '100%',
  height: '590px',
  layout: {
    type: 'ComplexHierarchicalTree',
    connectionPointOrigin: ConnectionPointOrigin.SamePoint,
    horizontalSpacing: 40,
    verticalSpacing: 40,
    horizontalAlignment: 'Left',
    //To set linear arrangement for the layout
    arrangement: ChildArrangement.Linear,
    verticalAlignment: 'Top',
    margin: { left: 0, right: 0, top: 0, bottom: 0 },
    orientation: 'TopToBottom',
  },
  getNodeDefaults: (obj: NodeModel) => {
    obj.width = 40;
    obj.height = 40;
    obj.shape = { type: 'Basic', shape: 'Rectangle' };
    obj.style = { fill: '#6BA5D7', strokeColor: 'none', strokeWidth: 2 };
    obj.borderWidth = 1;
    obj.backgroundColor = '#6BA5D7';
    return obj;
  },
  getConnectorDefaults: (connector: ConnectorModel, diagram: Diagram) => {
    connector.type = 'Orthogonal';
    connector.cornerRadius = 7;
    connector.targetDecorator.height = 7;
    connector.targetDecorator.width = 7;
    connector.style = { strokeColor: '#6BA5D7', strokeWidth: 1 };
    connector.targetDecorator.style.fill = '#6BA5D7';
    connector.targetDecorator.style.strokeColor = '#6BA5D7';
    return connector;
  },
  dataSourceSettings: {
    id: 'Name',
    parentId: 'ReportingPerson',
    dataSource: items,
  },
  snapSettings: { constraints: 0 },
});
diagram.appendTo('#element');
diagram.fitToPage({ mode: 'Width' });
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Diagram</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-diagrams/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-navigations/styles/fabric.css" rel="stylesheet" />
    <script src="systemjs.config.js"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id='element'></div>
    </div>
</body>

</html>

Enable routing for layout

In some complex parent-child relationships, connectors may overlap nodes in the layout. To address this issue, you can utilize the enableRouting functionality. This feature finds a connector path that avoids any obstacles.

To enable routing in the layout, set the enableRouting property to true.

The following example shows how to activate enableRouting in the layout:

import {
  Diagram,
  ConnectorModel,
  NodeModel,
  ConnectionPointOrigin,
  LineDistribution,
  ComplexHierarchicalTree,
  DataBinding,
} from '@syncfusion/ej2-diagrams';
import { DataManager, Query } from '@syncfusion/ej2-data';
Diagram.Inject(DataBinding, ComplexHierarchicalTree, LineDistribution);
//Initializes data source
let Data: object[] = [
  { Name: 'node11' },
  { Name: 'node12', ReportingPerson: ['node114'] },
  { Name: 'node13', ReportingPerson: ['node12'] },
  { Name: 'node14', ReportingPerson: ['node12'] },
  { Name: 'node15', ReportingPerson: ['node12'] },
  { Name: 'node116', ReportingPerson: ['node22', 'node12', 'node114'] },
  { Name: 'node21' },
  { Name: 'node22', ReportingPerson: ['node114'] },
  { Name: 'node222', ReportingPerson: ['node114'] },
  { Name: 'node2222', ReportingPerson: ['node114'] },
  { Name: 'node23', ReportingPerson: ['node22'] },
  { Name: 'node31' },
  { Name: 'node114', ReportingPerson: ['node11', 'node21', 'node31'] },
];
let items: DataManager = new DataManager(Data as JSON[], new Query().take(25));
// Initializes the diagram
let diagram: Diagram = new Diagram({
  width: '100%',
  height: '590px',
  layout: {
    type: 'ComplexHierarchicalTree',
    connectionPointOrigin: ConnectionPointOrigin.DifferentPoint,
    horizontalSpacing: 40,
    verticalSpacing: 40,
    horizontalAlignment: 'Left',
    //To enable routing for the layout
    enableRouting: true,
    verticalAlignment: 'Top',
    margin: { left: 0, right: 0, top: 0, bottom: 0 },
    orientation: 'TopToBottom',
  },
  getNodeDefaults: (obj: NodeModel) => {
    obj.width = 40;
    obj.height = 40;
    obj.shape = { type: 'Basic', shape: 'Rectangle' };
    obj.style = { fill: '#6BA5D7', strokeColor: 'none', strokeWidth: 2 };
    obj.borderWidth = 1;
    obj.backgroundColor = '#6BA5D7';
    return obj;
  },
  getConnectorDefaults: (connector: ConnectorModel, diagram: Diagram) => {
    connector.type = 'Orthogonal';
    connector.cornerRadius = 7;
    connector.targetDecorator.height = 7;
    connector.targetDecorator.width = 7;

    return connector;
  },
  dataSourceSettings: {
    id: 'Name',
    parentId: 'ReportingPerson',
    dataSource: items,
  },
  snapSettings: { constraints: 0 },
});
diagram.appendTo('#element');
diagram.fitToPage({ mode: 'Width' });
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Diagram</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-diagrams/styles/material.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/28.2.3/ej2-navigations/styles/fabric.css" rel="stylesheet" />
    <script src="systemjs.config.js"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id='element'></div>
    </div>
</body>

</html>