Organizational Chart Layout in React Diagram Component
21 Oct 202524 minutes to read
An organizational chart is a diagram that displays the hierarchical structure of an organization, showing reporting relationships and roles within the company. The React Diagram component provides specialized support for creating professional organizational charts through automatic layout algorithms. To create an organizational chart, set the type of layout should be set as an OrganizationalChart.
Organizational Chart with DataSource
This approach is ideal when working with dynamic data from databases, APIs, or when the organizational structure changes frequently. The component automatically generates nodes and connectors based on the provided data structure.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, HierarchicalTree } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Initializes data source
let data = [
{
Id: 'parent',
Role: 'Project Management',
},
{
Id: 1,
Role: 'R&D Team',
Team: 'parent',
},
{
Id: 3,
Role: 'Philosophy',
Team: '1',
},
{
Id: 4,
Role: 'Organization',
Team: '1',
},
{
Id: 5,
Role: 'Technology',
Team: '1',
},
{
Id: 7,
Role: 'Funding',
Team: '1',
},
{
Id: 8,
Role: 'Resource Allocation',
Team: '1',
},
{
Id: 9,
Role: 'Targeting',
Team: '1',
},
{
Id: 11,
Role: 'Evaluation',
Team: '1',
},
{
Id: 156,
Role: 'HR Team',
Team: 'parent',
},
{
Id: 13,
Role: 'Recruitment',
Team: '156',
},
{
Id: 112,
Role: 'Employee Relation',
Team: '156',
},
{
Id: 17,
Role: 'Production & Sales Team',
Team: 'parent',
},
{
Id: 119,
Role: 'Design',
Team: '17',
},
{
Id: 19,
Role: 'Operation',
Team: '17',
},
{
Id: 20,
Role: 'Support',
Team: '17',
},
{
Id: 21,
Role: 'Quality Assurance',
Team: '17',
},
{
Id: 23,
Role: 'Customer Interaction',
Team: '17',
},
{
Id: 24,
Role: 'Support and Maintenance',
Team: '17',
},
{
Id: 25,
Role: 'Task Coordination',
Team: '17',
}
];
let items = new DataManager(data, new Query().take(7));
export default function App() {
return (
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
snapSettings={{ constraints: 0 }}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//set layout type
type: 'OrganizationalChart'
}}
//Configures data source for diagram
dataSourceSettings={{
id: 'Id',
parentId: 'Team',
dataSource: items
}}
//Sets the default properties for nodes
getNodeDefaults={(node) => {
node.annotations = [{ content: node.data.Role }];
node.width = 75;
node.height = 40;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector) => {
connector.type = 'Orthogonal';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, HierarchicalTree]} />
</DiagramComponent>
);
}
// 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, ConnectorModel, DataBinding, NodeModel, HierarchicalTree } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Initializes data source
let data: object[] = [
{
Id: 'parent',
Role: 'Project Management',
},
{
Id: 1,
Role: 'R&D Team',
Team: 'parent',
},
{
Id: 3,
Role: 'Philosophy',
Team: '1',
},
{
Id: 4,
Role: 'Organization',
Team: '1',
},
{
Id: 5,
Role: 'Technology',
Team: '1',
},
{
Id: 7,
Role: 'Funding',
Team: '1',
},
{
Id: 8,
Role: 'Resource Allocation',
Team: '1',
},
{
Id: 9,
Role: 'Targeting',
Team: '1',
},
{
Id: 11,
Role: 'Evaluation',
Team: '1',
},
{
Id: 156,
Role: 'HR Team',
Team: 'parent',
},
{
Id: 13,
Role: 'Recruitment',
Team: '156',
},
{
Id: 112,
Role: 'Employee Relation',
Team: '156',
},
{
Id: 17,
Role: 'Production & Sales Team',
Team: 'parent',
},
{
Id: 119,
Role: 'Design',
Team: '17',
},
{
Id: 19,
Role: 'Operation',
Team: '17',
},
{
Id: 20,
Role: 'Support',
Team: '17',
},
{
Id: 21,
Role: 'Quality Assurance',
Team: '17',
},
{
Id: 23,
Role: 'Customer Interaction',
Team: '17',
},
{
Id: 24,
Role: 'Support and Maintenance',
Team: '17',
},
{
Id: 25,
Role: 'Task Coordination',
Team: '17',
}
];
let items: DataManager = new DataManager(data as JSON[], new Query().take(7));
export default function App() {
return (
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
snapSettings={{ constraints: 0 }}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//set layout type
type: 'OrganizationalChart'
}}
//Configures data source for diagram
dataSourceSettings={{
id: 'Id',
parentId: 'Team',
dataSource: items
}}
//Sets the default properties for nodes
getNodeDefaults={(node: NodeModel) => {
node.annotations = [{ content: (node.data as { Role: 'string' }).Role }];
node.width = 75;
node.height = 40;
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, HierarchicalTree]} />
</DiagramComponent>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram") as HTMLElement);
root.render(<App />);Note: When using organizational chart layout, both HierarchicalTree and DataBinding modules must be injected into the diagram component.
Organizational Chart with Nodes and Connectors
You can render an org-chart layout without using DataSource. The following code demonstrates how to render an org-chart layout without using data source.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, HierarchicalTree } from "@syncfusion/ej2-react-diagrams";
//Initialize nodes for diagram
let nodes = [
{ id: 'Project Management' },
{ id: 'R&D Team' },
{ id: 'Philosophy' },
{ id: 'Organization' },
{ id: 'Technology' },
{ id: 'Funding' },
{ id: 'Resource Allocation' },
{ id: 'Targeting' },
{ id: 'Evaluation' },
{ id: 'HR Team' },
{ id: 'Recruitment' },
{ id: 'Employee Relation' },
{ id: 'Production & Sales Team' },
{ id: 'Design' },
{ id: 'Operation' },
{ id: 'Support' },
{ id: 'Quality Assurance' },
{ id: 'Customer Interaction' },
{ id: 'Support and Maintenance' },
{ id: 'Task Coordination' },
];
//Initialize connectors for diagram
let connectors = [
{
id: 'Project Management-R&D Team',
sourceID: 'Project Management',
targetID: 'R&D Team',
},
{
id: 'R&D Team-Philosophy',
sourceID: 'R&D Team',
targetID: 'Philosophy'
},
{
id: 'R&D Team-Organization',
sourceID: 'R&D Team',
targetID: 'Organization',
},
{
id: 'R&D Team-Technology',
sourceID: 'R&D Team',
targetID: 'Technology'
},
{
id: 'R&D Team-Funding',
sourceID: 'R&D Team',
targetID: 'Funding'
},
{
id: 'R&D Team-Resource Allocation',
sourceID: 'R&D Team',
targetID: 'Resource Allocation',
},
{
id: 'R&D Team-Targeting',
sourceID: 'R&D Team',
targetID: 'Targeting'
},
{
id: 'R&D Team-Evaluation',
sourceID: 'R&D Team',
targetID: 'Evaluation'
},
{
id: 'Project Management-HR Team',
sourceID: 'Project Management',
targetID: 'HR Team',
},
{
id: 'HR Team-Recruitment',
sourceID: 'HR Team',
targetID: 'Recruitment'
},
{
id: 'HR Team-Employee Relation',
sourceID: 'HR Team',
targetID: 'Employee Relation',
},
{
id: 'Project Management-Production & Sales Team',
sourceID: 'Project Management',
targetID: 'Production & Sales Team',
},
{
id: 'Production & Sales Team-Design',
sourceID: 'Production & Sales Team',
targetID: 'Design',
},
{
id: 'Production & Sales Team-Operation',
sourceID: 'Production & Sales Team',
targetID: 'Operation',
},
{
id: 'Production & Sales Team-Support',
sourceID: 'Production & Sales Team',
targetID: 'Support',
},
{
id: 'Production & Sales Team-Quality Assurance',
sourceID: 'Production & Sales Team',
targetID: 'Quality Assurance',
},
{
id: 'Production & Sales Team-Customer Interaction',
sourceID: 'Production & Sales Team',
targetID: 'Customer Interaction',
},
{
id: 'Production & Sales Team-Support and Maintenance',
sourceID: 'Production & Sales Team',
targetID: 'Support and Maintenance',
},
{
id: 'Production & Sales Team-Task Coordination',
sourceID: 'Production & Sales Team',
targetID: 'Task Coordination',
},
];
export default function App() {
return (
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
nodes={nodes}
connectors={connectors}
snapSettings={{ constraints: 0 }}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//set layout type
type: 'OrganizationalChart'
}}
//Sets the default properties for nodes
getNodeDefaults={(node) => {
node.annotations = [{ content: node.id }];
node.width = 75;
node.height = 40;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector) => {
connector.type = 'Orthogonal';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, HierarchicalTree]} />
</DiagramComponent>
);
}
// 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, ConnectorModel, DataBinding, NodeModel, HierarchicalTree } from "@syncfusion/ej2-react-diagrams";
//Initialize nodes for diagram
let nodes: NodeModel[] = [
{ id: 'Project Management' },
{ id: 'R&D Team' },
{ id: 'Philosophy' },
{ id: 'Organization' },
{ id: 'Technology' },
{ id: 'Funding' },
{ id: 'Resource Allocation' },
{ id: 'Targeting' },
{ id: 'Evaluation' },
{ id: 'HR Team' },
{ id: 'Recruitment' },
{ id: 'Employee Relation' },
{ id: 'Production & Sales Team' },
{ id: 'Design' },
{ id: 'Operation' },
{ id: 'Support' },
{ id: 'Quality Assurance' },
{ id: 'Customer Interaction' },
{ id: 'Support and Maintenance' },
{ id: 'Task Coordination' },
];
//Initialize connectors for diagram
let connectors: ConnectorModel[] = [
{
id: 'Project Management-R&D Team',
sourceID: 'Project Management',
targetID: 'R&D Team',
},
{
id: 'R&D Team-Philosophy',
sourceID: 'R&D Team',
targetID: 'Philosophy'
},
{
id: 'R&D Team-Organization',
sourceID: 'R&D Team',
targetID: 'Organization',
},
{
id: 'R&D Team-Technology',
sourceID: 'R&D Team',
targetID: 'Technology'
},
{
id: 'R&D Team-Funding',
sourceID: 'R&D Team',
targetID: 'Funding'
},
{
id: 'R&D Team-Resource Allocation',
sourceID: 'R&D Team',
targetID: 'Resource Allocation',
},
{
id: 'R&D Team-Targeting',
sourceID: 'R&D Team',
targetID: 'Targeting'
},
{
id: 'R&D Team-Evaluation',
sourceID: 'R&D Team',
targetID: 'Evaluation'
},
{
id: 'Project Management-HR Team',
sourceID: 'Project Management',
targetID: 'HR Team',
},
{
id: 'HR Team-Recruitment',
sourceID: 'HR Team',
targetID: 'Recruitment'
},
{
id: 'HR Team-Employee Relation',
sourceID: 'HR Team',
targetID: 'Employee Relation',
},
{
id: 'Project Management-Production & Sales Team',
sourceID: 'Project Management',
targetID: 'Production & Sales Team',
},
{
id: 'Production & Sales Team-Design',
sourceID: 'Production & Sales Team',
targetID: 'Design',
},
{
id: 'Production & Sales Team-Operation',
sourceID: 'Production & Sales Team',
targetID: 'Operation',
},
{
id: 'Production & Sales Team-Support',
sourceID: 'Production & Sales Team',
targetID: 'Support',
},
{
id: 'Production & Sales Team-Quality Assurance',
sourceID: 'Production & Sales Team',
targetID: 'Quality Assurance',
},
{
id: 'Production & Sales Team-Customer Interaction',
sourceID: 'Production & Sales Team',
targetID: 'Customer Interaction',
},
{
id: 'Production & Sales Team-Support and Maintenance',
sourceID: 'Production & Sales Team',
targetID: 'Support and Maintenance',
},
{
id: 'Production & Sales Team-Task Coordination',
sourceID: 'Production & Sales Team',
targetID: 'Task Coordination',
},
];
export default function App() {
return (
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
nodes={nodes}
connectors={connectors}
snapSettings={{ constraints: 0 }}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//set layout type
type: 'OrganizationalChart'
}}
//Sets the default properties for nodes
getNodeDefaults={(node: NodeModel) => {
node.annotations = [{ content: node.id }];
node.width = 75;
node.height = 40;
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, HierarchicalTree]} />
</DiagramComponent>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram") as HTMLElement);
root.render(<App />);
Advanced Layout Customization with getLayoutInfo
Organizational chart layout starts parsing from root and iterate through all its child elements. The getLayoutInfo method provides granular control over how each subtree within the organizational chart is arranged. This method is invoked for every node during the layout process, allowing customization of orientation, alignment, spacing, and special node types like assistants.
The organizational chart layout engine parses the hierarchy starting from the root node and processes each subtree. By overriding the getLayoutInfo method, developers can customize the arrangement of child nodes based on specific business requirements.
getLayoutInfo Parameters
The getLayoutInfo method accepts the following parameters:
- node: The parent node for which layout options are being configured.
- options: Configuration object containing customizable layout properties.
Layout Options Properties
The following table illustrates the properties that “options” argument takes.
| Property | Description | Default Value |
|---|---|---|
| options.assistants | By default, the collection is empty. When any of the child nodes have to be set as Assistant, you can remove from children collection and have to insert into assistants collection. | Empty array |
| options.orientation | Gets or sets the organizational chart orientation. | SubTreeOrientation.Vertical |
| options.type | Gets or sets the chart organizational chart type. | For horizontal chart orientation:SubTreeAlignments.Center and for vertical chart orientation:SubTreeAlignments.Alternate |
| options.offset | Offset is the horizontal space to be left between parent and child nodes. | 20 pixels applicable only for vertical chart orientations. |
| options.hasSubTree | Gets whether the node contains subtrees. | Boolean |
| options.level | Gets the depth of the node from layout root. | Number |
| options.enableRouting | By default, connections are routed based on the chart type and orientations. This property gets or sets whether default routing is to be enabled or disabled. | true |
| options.rows | Sets the number of rows on which the child nodes will be arranged. Applicable only for balanced type horizontal tree. | Number |
Orientation and Alignment Options
The following table describes the available chart orientations and their corresponding alignment types:
| Orientation | Type | Description | Example |
|---|---|---|---|
| Horizontal | Left | Arranges the child nodes horizontally at the left side of the parent. | |
| Right | Arranges the child nodes horizontally at the right side of the parent. | ||
| Center | Arranges the children like standard tree layout orientation. | ||
| Balanced | Arranges the leaf level child nodes in multiple rows. | ||
| Vertical | Left | Arranges the children vertically at the left side of the parent. | |
| Right | Arranges the children vertically at the right side of the parent. | ||
| Alternate | Arranges the children vertically at both left and right sides of the parent. |
Horizontal Subtree Orientation Example
The following example demonstrates customizing subtree alignment for horizontal organizational structures:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, HierarchicalTree } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Initializes data source
let data = [
{ Id: 1, Role: 'General Manager' },
{ Id: 2, Role: 'Assistant Manager', Team: 1 },
{ Id: 3, Role: 'Human Resource Manager', Team: 1 },
{ Id: 4, Role: 'Design Manager', Team: 1 },
{ Id: 5, Role: 'Operation Manager', Team: 1 },
{ Id: 6, Role: 'Marketing Manager', Team: 1 },
];
let items = new DataManager(data, new Query().take(7));
export default function App() {
let diagramInstance;
let alignmentInstance;
function onAlignmentChange() {
const args = alignmentInstance.value;
diagramInstance.layout.getLayoutInfo = (node, options) => {
if (!options.hasSubTree) {
options.type = args;
options.orientation = 'Horizontal';
}
};
};
return (
<div>
<label htmlFor="alignment">Alignment: </label>
<select name="alignment" id="alignment" onChange={onAlignmentChange}
ref={(alignment) => (alignmentInstance = alignment)}
>
<option value="Center">Center</option>
<option value="Right">Right</option>
<option value="Left">Left</option>
<option value="Balanced">Balanced</option>
</select>
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
ref={(diagram) => (diagramInstance = diagram)}
snapSettings={{ constraints: 0 }}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//Sets layout type
type: 'OrganizationalChart',
// define the getLayoutInfo
getLayoutInfo: (node, options) => {
if (!options.hasSubTree) {
options.type = 'Center';
options.orientation = 'Horizontal';
}
}
}}
//Configures data source for diagram
dataSourceSettings={{
id: 'Id',
parentId: 'Team',
dataSource: items
}}
//Sets the default properties for nodes
getNodeDefaults={(node) => {
node.annotations = [{ content: node.data.Role }];
node.width = 150;
node.height = 50;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector) => {
connector.type = 'Orthogonal';
(connector.targetDecorator).shape = 'None';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, HierarchicalTree]} />
</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, ConnectorModel, DataBinding, NodeModel, HierarchicalTree, SubTreeAlignments, TreeInfo, DecoratorModel } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Initializes data source
let data: object[] = [
{ Id: 1, Role: 'General Manager' },
{ Id: 2, Role: 'Assistant Manager', Team: 1 },
{ Id: 3, Role: 'Human Resource Manager', Team: 1 },
{ Id: 4, Role: 'Design Manager', Team: 1 },
{ Id: 5, Role: 'Operation Manager', Team: 1 },
{ Id: 6, Role: 'Marketing Manager', Team: 1 },
];
let items: DataManager = new DataManager(data as JSON[], new Query().take(7));
export default function App() {
let diagramInstance: DiagramComponent;
let alignmentInstance: HTMLSelectElement;
function onAlignmentChange() {
const args = alignmentInstance.value;
diagramInstance.layout.getLayoutInfo = (node: Node, options: TreeInfo) => {
if (!options.hasSubTree) {
options.type = (args as SubTreeAlignments);
options.orientation = 'Horizontal';
}
};
};
return (
<div>
<label htmlFor="alignment">Alignment: </label>
<select name="alignment" id="alignment" onChange={onAlignmentChange}
ref={(alignment: any) => (alignmentInstance = alignment)}
>
<option value="Center">Center</option>
<option value="Right">Right</option>
<option value="Left">Left</option>
<option value="Balanced">Balanced</option>
</select>
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
ref={(diagram: any) => (diagramInstance = diagram)}
snapSettings={{ constraints: 0 }}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//Sets layout type
type: 'OrganizationalChart',
// define the getLayoutInfo
getLayoutInfo: (node: Node, options: TreeInfo) => {
if (!options.hasSubTree) {
options.type = 'Center';
options.orientation = 'Horizontal';
}
}
}}
//Configures data source for diagram
dataSourceSettings={{
id: 'Id',
parentId: 'Team',
dataSource: items
}}
//Sets the default properties for nodes
getNodeDefaults={(node: NodeModel) => {
node.annotations = [{ content: (node.data as { Role: 'string' }).Role }];
node.width = 150;
node.height = 50;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector: ConnectorModel) => {
connector.type = 'Orthogonal';
(connector.targetDecorator as DecoratorModel).shape = 'None';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, HierarchicalTree]} />
</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 />);Vertical Subtree Orientation Example
This example shows how to implement vertical arrangement for leaf-level organizational trees:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, HierarchicalTree } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Initializes data source
let data = [
{ Id: 1, Role: 'General Manager' },
{ Id: 2, Role: 'Assistant Manager', Team: 1 },
{ Id: 3, Role: 'Human Resource Manager', Team: 1 },
{ Id: 4, Role: 'Design Manager', Team: 1 },
{ Id: 5, Role: 'Operation Manager', Team: 1 },
{ Id: 6, Role: 'Marketing Manager', Team: 1 },
];
let items = new DataManager(data, new Query().take(7));
export default function App() {
let diagramInstance;
let alignmentInstance;
function onAlignmentChange() {
const args = alignmentInstance.value;
diagramInstance.layout.getLayoutInfo = (node, options) => {
if (!options.hasSubTree) {
options.type = args;
options.orientation = 'Vertical';
}
};
};
return (
<div>
<label htmlFor="alignment">Alignment: </label>
<select name="alignment" id="alignment" onChange={onAlignmentChange}
ref={(alignment) => (alignmentInstance = alignment)}
>
<option value="Left">Left</option>
<option value="Right">Right</option>
<option value="Alternate">Alternate</option>
</select>
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
ref={(diagram) => (diagramInstance = diagram)}
snapSettings={{ constraints: 0 }}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//Sets layout type
type: 'OrganizationalChart',
// define the getLayoutInfo
getLayoutInfo: (node, options) => {
if (!options.hasSubTree) {
options.type = 'Left';
options.orientation = 'Vertical';
}
}
}}
//Configures data source for diagram
dataSourceSettings={{
id: 'Id',
parentId: 'Team',
dataSource: items
}}
//Sets the default properties for nodes
getNodeDefaults={(node) => {
node.annotations = [{ content: node.data.Role }];
node.width = 150;
node.height = 50;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector) => {
connector.type = 'Orthogonal';
(connector.targetDecorator).shape = 'None';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, HierarchicalTree]} />
</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, ConnectorModel, DataBinding, NodeModel, HierarchicalTree, SubTreeAlignments, TreeInfo, DecoratorModel } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Initializes data source
let data: object[] = [
{ Id: 1, Role: 'General Manager' },
{ Id: 2, Role: 'Assistant Manager', Team: 1 },
{ Id: 3, Role: 'Human Resource Manager', Team: 1 },
{ Id: 4, Role: 'Design Manager', Team: 1 },
{ Id: 5, Role: 'Operation Manager', Team: 1 },
{ Id: 6, Role: 'Marketing Manager', Team: 1 },
];
let items: DataManager = new DataManager(data as JSON[], new Query().take(7));
export default function App() {
let diagramInstance: DiagramComponent;
let alignmentInstance: HTMLSelectElement;
function onAlignmentChange() {
const args = alignmentInstance.value;
diagramInstance.layout.getLayoutInfo = (node: Node, options: TreeInfo) => {
if (!options.hasSubTree) {
options.type = (args as SubTreeAlignments);
options.orientation = 'Vertical';
}
};
};
return (
<div>
<label htmlFor="alignment">Alignment: </label>
<select name="alignment" id="alignment" onChange={onAlignmentChange}
ref={(alignment: any) => (alignmentInstance = alignment)}
>
<option value="Left">Left</option>
<option value="Right">Right</option>
<option value="Alternate">Alternate</option>
</select>
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
ref={(diagram: any) => (diagramInstance = diagram)}
snapSettings={{ constraints: 0 }}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//Sets layout type
type: 'OrganizationalChart',
// define the getLayoutInfo
getLayoutInfo: (node: Node, options: TreeInfo) => {
if (!options.hasSubTree) {
options.type = 'Left';
options.orientation = 'Vertical';
}
}
}}
//Configures data source for diagram
dataSourceSettings={{
id: 'Id',
parentId: 'Team',
dataSource: items
}}
//Sets the default properties for nodes
getNodeDefaults={(node: NodeModel) => {
node.annotations = [{ content: (node.data as { Role: 'string' }).Role }];
node.width = 150;
node.height = 50;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector: ConnectorModel) => {
connector.type = 'Orthogonal';
(connector.targetDecorator as DecoratorModel).shape = 'None';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, HierarchicalTree]} />
</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 />);Assistant Nodes
Assistant nodes represent positions with specialized relationships to their parent, such as executive assistants or advisor’s. These nodes are positioned in a dedicated area separate from regular child nodes. To designate a node as an assistant, add it to the assistants collection within the getLayoutInfo options parameter.
The following code example illustrates how to add assistants to layout.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, HierarchicalTree } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Initializes data source
let data = [
{ Id: 1, Role: 'General Manager' },
{ Id: 2, Role: 'Assistant Manager', Team: 1 },
{ Id: 3, Role: 'Human Resource Manager', Team: 1 },
{ Id: 4, Role: 'Design Manager', Team: 1 },
{ Id: 5, Role: 'Operation Manager', Team: 1 },
{ Id: 6, Role: 'Marketing Manager', Team: 1 },
];
let items = new DataManager(data, new Query().take(7));
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
snapSettings={{ constraints: 0 }}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//Sets layout type
type: 'OrganizationalChart',
// define the getLayoutInfo
getLayoutInfo: (node, options) => {
if (node.data['Role'] === 'General Manager') {
options.assistants.push(options.children[0]);
options.children.splice(0, 1);
}
if (!options.hasSubTree) {
options.type = 'Center';
options.orientation = 'Horizontal';
}
}
}}
//Configures data source for diagram
dataSourceSettings={{
id: 'Id',
parentId: 'Team',
dataSource: items
}}
//Sets the default properties for nodes
getNodeDefaults={(node) => {
node.annotations = [{ content: node.data.Role }];
node.width = 150;
node.height = 50;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector) => {
connector.type = 'Orthogonal';
connector.targetDecorator.shape = 'None';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, HierarchicalTree]} />
</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, ConnectorModel, DataBinding, NodeModel, HierarchicalTree, TreeInfo, DecoratorModel } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Initializes data source
let data: object[] = [
{ Id: 1, Role: 'General Manager' },
{ Id: 2, Role: 'Assistant Manager', Team: 1 },
{ Id: 3, Role: 'Human Resource Manager', Team: 1 },
{ Id: 4, Role: 'Design Manager', Team: 1 },
{ Id: 5, Role: 'Operation Manager', Team: 1 },
{ Id: 6, Role: 'Marketing Manager', Team: 1 },
];
let items: DataManager = new DataManager(data as JSON[], new Query().take(7));
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
snapSettings={{ constraints: 0 }}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//Sets layout type
type: 'OrganizationalChart',
// define the getLayoutInfo
getLayoutInfo: (node: Node | any, options: TreeInfo) => {
if (node.data['Role'] === 'General Manager') {
(options.assistants as string[]).push((options.children as string[])[0]);
(options.children as string[]).splice(0, 1);
}
if (!options.hasSubTree) {
options.type = 'Center';
options.orientation = 'Horizontal';
}
}
}}
//Configures data source for diagram
dataSourceSettings={{
id: 'Id',
parentId: 'Team',
dataSource: items
}}
//Sets the default properties for nodes
getNodeDefaults={(node: NodeModel) => {
node.annotations = [{ content: (node.data as { Role: 'string' }).Role }];
node.width = 150;
node.height = 50;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector: ConnectorModel) => {
connector.type = 'Orthogonal';
(connector.targetDecorator as DecoratorModel).shape = 'None';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, HierarchicalTree]} />
</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: Assistant nodes cannot have child nodes and serve as terminal positions in the organizational hierarchy.
Best Practices
- Use the DataSource approach for dynamic organizational structures that may change frequently.
- Implement the manual approach when requiring custom node designs or static hierarchies.
- Consider using assistant nodes for specialized roles like executive assistants or advisory positions.
- Apply appropriate orientation and alignment settings based on the size and complexity of the organization.
- Test layout performance with large datasets and consider implementing virtualization for extensive organizational charts.