Complex Hierarchical Tree Layout in React Diagram
21 Aug 202624 minutes to read
Complex hierarchical tree layout arranges nodes in a tree-like structure where child nodes can have multiple parent nodes, creating interconnected relationships beyond traditional single-parent hierarchies. This layout type is ideal for organizational charts with dotted-line relationships, project dependencies, or any structure where entities report to multiple authorities. This layout extends the standard hierarchical tree layout to support these complex relationships.
To create a complex hierarchical tree, set the type property of layout to ComplexHierarchicalTree.
NOTE
To render the complex hierarchical tree layout, you must inject the
ComplexHierarchicalTreemodule into theDiagramComponentby adding<Inject services={[ComplexHierarchicalTree]} />inside the component.
Complex Hierarchical Tree Layout with Nodes and Connectors
This example demonstrates how to create a complex hierarchical tree layout by manually defining nodes and connectors. The layout automatically positions nodes based on their hierarchical relationships while handling multiple parent-child connections.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, ComplexHierarchicalTree } from "@syncfusion/ej2-react-diagrams";
//Initialize nodes for diagram
let nodes = [
{ id: 'node1' },
{ id: 'node2' },
{ id: 'node3' },
{ id: 'node4' },
{ id: 'node5' },
{ id: 'node6' },
{ id: 'node7' },
];
//Initialize connectors for diagram
let connectors = [
{ 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' },
];
//Initialize layout settings for the diagram
const layout = {
//Sets layout type
type: 'ComplexHierarchicalTree',
};
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
nodes={nodes}
connectors={connectors}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Sets the default properties for nodes
getNodeDefaults={(node) => {
node.width = 70; node.height = 70;
node.annotations = [{ content: node.id }];
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector) => {
connector.type = 'Orthogonal';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, ComplexHierarchicalTree]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram"));
root.render(<App />);import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, NodeModel, ConnectorModel, DataBinding,
ComplexHierarchicalTree, LayoutModel } from "@syncfusion/ej2-react-diagrams";
//Initialize nodes for diagram
let nodes: NodeModel[] = [
{ id: 'node1' },
{ id: 'node2' },
{ id: 'node3' },
{ id: 'node4' },
{ id: 'node5' },
{ id: 'node6' },
{ id: 'node7' },
];
//Initialize connectors for diagram
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' },
];
//Initialize layout settings for the diagram
const layout: LayoutModel = {
//Sets layout type
type: 'ComplexHierarchicalTree',
};
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
nodes={nodes}
connectors={connectors}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Sets the default properties for nodes
getNodeDefaults={(node: NodeModel) => {
node.width = 70; node.height = 70;
node.annotations = [{ content: node.id }];
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector: ConnectorModel) => {
connector.type = 'Orthogonal';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, ComplexHierarchicalTree]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram") as HTMLElement);
root.render(<App />);Complex Hierarchical Tree Layout with DataSource
When working with large datasets, binding the layout to a data source provides better maintainability and dynamic content management. The following example shows how to create a complex hierarchical tree using a data source configuration.
NOTE
In the data source, entries that do not reference any other node are treated as root nodes. To define multiple root nodes, add more such top-level entries as shown below.
[
{ "id": "root1", "name": "CEO" },
{ "id": "root2", "name": "CTO" },
{ "id": "node1", "name": "Manager A","parent": ["root1", "root2"] }
]
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, ComplexHierarchicalTree } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Initializes data source
let data = [
{ "Name": "node11" },
{ "Name": "node12", "ReportingPerson": ["node114"] },
{ "Name": "node13", "ReportingPerson": ["node12"] },
{ "Name": "node14", "ReportingPerson": ["node12"] },
{ "Name": "node15", "ReportingPerson": ["node12"] },
{ "Name": "node16", "ReportingPerson": [] },
{ "Name": "node17", "ReportingPerson": ["node13", "node14", "node15"] },
{ "Name": "node18", "ReportingPerson": [] },
{ "Name": "node19", "ReportingPerson": ["node16", "node17", "node18"] },
{ "Name": "node110", "ReportingPerson": ["node16", "node17", "node18"] },
{ "Name": "node111", "ReportingPerson": ["node16", "node17", "node18", "node116"] },
{ "Name": "node21" },
{ "Name": "node22", "ReportingPerson": ["node114"] },
{ "Name": "node23", "ReportingPerson": ["node22"] },
{ "Name": "node24", "ReportingPerson": ["node22"] },
{ "Name": "node25", "ReportingPerson": ["node22"] },
{ "Name": "node26", "ReportingPerson": [] },
{ "Name": "node27", "ReportingPerson": ["node23", "node24", "node25"] },
{ "Name": "node28", "ReportingPerson": [] },
{ "Name": "node29", "ReportingPerson": ["node26", "node27", "node28", "node116"] },
{ "Name": "node210", "ReportingPerson": ["node26", "node27", "node28"] },
{ "Name": "node211", "ReportingPerson": ["node26", "node27", "node28"] },
{ "Name": "node31" },
{ "Name": "node114", "ReportingPerson": ["node11", "node21", "node31"] },
{ "Name": "node116", "ReportingPerson": ["node12", "node22"], }
];
let items = new DataManager(data, new Query().take(7));
//Initialize layout settings for the diagram
const layout = {
//Sets layout type
type: 'ComplexHierarchicalTree'
};
//Configures data source for diagram
const dataSourceSettings = {
id: 'Name',
parentId: 'ReportingPerson',
dataSource: items
};
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"700px"}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Configures data source for diagram
dataSourceSettings={dataSourceSettings}
//Sets the default properties for nodes
getNodeDefaults={(node) => {
node.width = 70; node.height = 70;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector) => {
connector.type = 'Orthogonal';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, ComplexHierarchicalTree]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram"));
root.render(<App />);import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, NodeModel, ConnectorModel, DataBinding,
ComplexHierarchicalTree, LayoutModel, DataSourceModel } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//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": "node16", "ReportingPerson": [] },
{ "Name": "node17", "ReportingPerson": ["node13", "node14", "node15"] },
{ "Name": "node18", "ReportingPerson": [] },
{ "Name": "node19", "ReportingPerson": ["node16", "node17", "node18"] },
{ "Name": "node110", "ReportingPerson": ["node16", "node17", "node18"] },
{ "Name": "node111", "ReportingPerson": ["node16", "node17", "node18", "node116"] },
{ "Name": "node21" },
{ "Name": "node22", "ReportingPerson": ["node114"] },
{ "Name": "node23", "ReportingPerson": ["node22"] },
{ "Name": "node24", "ReportingPerson": ["node22"] },
{ "Name": "node25", "ReportingPerson": ["node22"] },
{ "Name": "node26", "ReportingPerson": [] },
{ "Name": "node27", "ReportingPerson": ["node23", "node24", "node25"] },
{ "Name": "node28", "ReportingPerson": [] },
{ "Name": "node29", "ReportingPerson": ["node26", "node27", "node28", "node116"] },
{ "Name": "node210", "ReportingPerson": ["node26", "node27", "node28"] },
{ "Name": "node211", "ReportingPerson": ["node26", "node27", "node28"] },
{ "Name": "node31" },
{ "Name": "node114", "ReportingPerson": ["node11", "node21", "node31"] },
{ "Name": "node116", "ReportingPerson": ["node12", "node22"], }
];
let items: DataManager = new DataManager(data as JSON[], new Query().take(7));
//Initialize layout settings for the diagram
const layout: LayoutModel = {
//Sets layout type
type: 'ComplexHierarchicalTree'
};
//Configures data source for diagram
const dataSourceSettings: DataSourceModel = {
id: 'Name',
parentId: 'ReportingPerson',
dataSource: items
};
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"700px"}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Configures data source for diagram
dataSourceSettings={dataSourceSettings}
//Sets the default properties for nodes
getNodeDefaults={(node: NodeModel) => {
node.width = 70; node.height = 70;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector: ConnectorModel) => {
connector.type = 'Orthogonal';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, ComplexHierarchicalTree]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram") as HTMLElement);
root.render(<App />);
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 prevents connector overlap by controlling how multiple connectors from a single parent node are positioned. Without line distribution, connectors may overlap and create visual confusion in complex layouts. The connectionPointOrigin property of layout is used to enable or disable the line distribution in layout.
The connectionPointOrigin property accepts the following values:
- SamePoint (default): Connectors connect at the same point in the layout.
- DifferentPoint: Connectors connect at different points in the layout.
The following code example illustrates how to create a complex hierarchical tree with line distribution.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, ComplexHierarchicalTree,
ConnectionPointOrigin, LineDistribution } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Initializes data source
let data = [
{ "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 = new DataManager(data, new Query().take(7));
//Initialize layout settings for the diagram
const layout = {
//Sets layout type
type: 'ComplexHierarchicalTree',
connectionPointOrigin: ConnectionPointOrigin.DifferentPoint,
};
//Configures data source for diagram
const dataSourceSettings = {
id: 'Name',
parentId: 'ReportingPerson',
dataSource: items
};
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"700px"}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Configures data source for diagram
dataSourceSettings={dataSourceSettings}
//Sets the default properties for nodes
getNodeDefaults={(node) => {
node.width = 40; node.height = 40;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector) => {
connector.type = 'Orthogonal';
connector.cornerRadius = 7;
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, ComplexHierarchicalTree, LineDistribution]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram"));
root.render(<App />);import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, NodeModel, ConnectorModel, DataBinding,
ComplexHierarchicalTree, ConnectionPointOrigin, LineDistribution, LayoutModel, DataSourceModel } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//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(7));
//Initialize layout settings for the diagram
const layout: LayoutModel = {
//Sets layout type
type: 'ComplexHierarchicalTree',
connectionPointOrigin: ConnectionPointOrigin.DifferentPoint,
};
//Configures data source for diagram
const dataSourceSettings: DataSourceModel = {
id: 'Name',
parentId: 'ReportingPerson',
dataSource: items
};
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"700px"}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Configures data source for diagram
dataSourceSettings={dataSourceSettings}
//Sets the default properties for nodes
getNodeDefaults={(node: NodeModel) => {
node.width = 40; node.height = 40;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector: ConnectorModel) => {
connector.type = 'Orthogonal';
connector.cornerRadius = 7;
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, ComplexHierarchicalTree, LineDistribution ]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram") as HTMLElement);
root.render(<App />);NOTE
If you want to use line distribution in diagram layout, you need to inject the
LineDistributionmodule by adding<Inject services={[LineDistribution]} />inside theDiagramComponent.

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. Use the arrangement property to control this feature:
The arrangement property accepts the following values:
- Nonlinear (default): Child nodes are arranged based on available space.
- Linear: Child nodes are arranged in a straight line with the parent centered.
When line distribution is enabled, linear arrangement is also activated by default.
NOTE
If you want to use linear arrangement in the diagram layout, you need to inject the
LineDistributionmodule. Linear arrangement is applicable only to the complex hierarchical tree layout.
The following code illustrates how to allow a linear arrangement in diagram layout.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, ComplexHierarchicalTree, LineDistribution,
ChildArrangement } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Initializes data source
let data = [
{ "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 = new DataManager(data, new Query().take(7));
//Initialize layout settings for the diagram
const layout = {
//Sets layout type
type: 'ComplexHierarchicalTree',
arrangement: ChildArrangement.Linear,
};
//Configures data source for diagram
const dataSourceSettings = {
id: 'Name',
parentId: 'ReportingPerson',
dataSource: items
};
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"700px"}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Configures data source for diagram
dataSourceSettings={dataSourceSettings}
//Sets the default properties for nodes
getNodeDefaults={(node) => {
node.width = 40; node.height = 40;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector) => {
connector.type = 'Orthogonal';
connector.cornerRadius = 7;
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, ComplexHierarchicalTree, LineDistribution]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram"));
root.render(<App />);import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, NodeModel, ConnectorModel, DataBinding, ComplexHierarchicalTree,
LineDistribution, ChildArrangement, LayoutModel, DataSourceModel } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//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(7));
//Initialize layout settings for the diagram
const layout: LayoutModel = {
//Sets layout type
type: 'ComplexHierarchicalTree',
arrangement: ChildArrangement.Linear,
};
//Configures data source for diagram
const dataSourceSettings: DataSourceModel = {
id: 'Name',
parentId: 'ReportingPerson',
dataSource: items
};
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"700px"}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Configures data source for diagram
dataSourceSettings={dataSourceSettings}
//Sets the default properties for nodes
getNodeDefaults={(node: NodeModel) => {
node.width = 40; node.height = 40;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector: ConnectorModel) => {
connector.type = 'Orthogonal';
connector.cornerRadius = 7;
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, ComplexHierarchicalTree, LineDistribution]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram") as HTMLElement);
root.render(<App />);Enable Routing for Layout
In complex diagrams with intricate parent-child relationships, connectors may pass through or overlap with nodes, making the diagram difficult to read. Routing functionality automatically calculates connector paths that avoid intersecting with nodes and other obstacles.
Set the enableRouting property to true to activate intelligent connector routing.
The following example shows how to enable routing in the layout:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, ComplexHierarchicalTree, LineDistribution } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Initializes data source
let data = [
{ Name: 'node11' },
{ Name: 'node12', ReportingPerson: ['node114'] },
{ Name: 'node13', ReportingPerson: ['node12'] },
{ Name: 'node14', ReportingPerson: ['node12'] },
{ Name: 'node15', ReportingPerson: ['node12'] },
{ Name: 'node16', 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 = new DataManager(data, new Query().take(7));
//Initialize layout settings for the diagram
const layout = {
//Sets layout type
type: 'ComplexHierarchicalTree',
enableRouting: true
};
//Configures data source for diagram
const dataSourceSettings = {
id: 'Name',
parentId: 'ReportingPerson',
dataSource: items
};
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"700px"}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Configures data source for diagram
dataSourceSettings={dataSourceSettings}
//Sets the default properties for nodes
getNodeDefaults={(node) => {
node.width = 40; node.height = 40;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector) => {
connector.type = 'Orthogonal';
connector.cornerRadius = 7;
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, ComplexHierarchicalTree, LineDistribution]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram"));
root.render(<App />);import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, NodeModel, ConnectorModel, DataBinding, ComplexHierarchicalTree, LineDistribution, LayoutModel, DataSourceModel } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//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: 'node16', 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(7));
//Initialize layout settings for the diagram
const layout: LayoutModel = {
//Sets layout type
type: 'ComplexHierarchicalTree',
enableRouting: true
};
//Configures data source for diagram
const dataSourceSettings: DataSourceModel = {
id: 'Name',
parentId: 'ReportingPerson',
dataSource: items
};
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"700px"}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Configures data source for diagram
dataSourceSettings={dataSourceSettings}
//Sets the default properties for nodes
getNodeDefaults={(node: NodeModel) => {
node.width = 40; node.height = 40;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector: ConnectorModel) => {
connector.type = 'Orthogonal';
connector.cornerRadius = 7;
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, ComplexHierarchicalTree, LineDistribution ]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram") as HTMLElement);
root.render(<App />);Best Practices
- Use data source binding for dynamic content and better maintainability.
- Enable line distribution when dealing with nodes that have multiple connections.
- Consider enabling routing for complex layouts to improve visual clarity.
- Test layout performance with large datasets and optimize as needed.
- Ensure proper module injection for advanced features like line distribution.
Troubleshooting
| Issue | Possible Cause | Suggested Fix |
|---|---|---|
| Layout is not applied to the diagram | Required layout module (for example, ComplexHierarchicalTree) is not injected. |
Add <Inject services={[ComplexHierarchicalTree]} /> inside the DiagramComponent. |
| Connectors overlap or render at the same point |
connectionPointOrigin is set to SamePoint (default) with multiple connectors. |
Set connectionPointOrigin: ConnectionPointOrigin.DifferentPoint in the layout configuration. |
| Linear arrangement has no effect |
LineDistribution module is not injected. |
Add <Inject services={[LineDistribution]} /> inside the DiagramComponent. |
| Connectors pass through other nodes | Routing is disabled. | Set enableRouting: true in the layout configuration. |
| Nodes are not arranged hierarchically when using a data source | Data entries are not correctly linked via the parent reference. | Ensure each non-root node references the id of its parent in the configured field. |