# diagram-organization-chart

> Organization chart arranges local employee data in a horizontally aligned hierarchy.

**Framework:** react  **Component:** Diagram  **Variant:** organization-chart

## Get this item

**If you are an agent, fetch the JSON.** Source is inlined, so one request is enough and no tooling is required:

```
GET https://ai.syncfusion.com/r/react/ts/diagram-organization-chart.json
```

**Install Package(s)**

```bash
npm install @syncfusion/ej2-react-diagrams @syncfusion/ej2-react-inputs @syncfusion/ej2-data
```

**Notes**

- Syncfusion release: 2026 Volume 2 (v34.1.29)
- The Syncfusion package is licensed. The composition in this file is source you own and edit. See https://ai.syncfusion.com/licensing.md

## Source files

### src/components/diagram-organization-chart/Diagram.tsx

```tsx
import {
  type TreeInfo,
  Node,
  type SubTreeOrientation,
  type LayoutOrientation,
  type SubTreeAlignments,
  LayoutAnimation,
  HierarchicalTree,
  DataBinding,
  DiagramComponent,
  Diagram,
  type NodeModel,
  type ConnectorModel,
  ConnectorConstraints,
  SnapConstraints,
  Inject,
  DiagramTools
} from "@syncfusion/ej2-react-diagrams";
import { DataManager } from "@syncfusion/ej2-data";
import { NumericTextBoxComponent } from "@syncfusion/ej2-react-inputs";

export interface EmployeeInfo {
  Role: string;
  color: string;
}

export interface EmployeeInfo {
  Name: string;
}

let localBindData = [
    { 'Id': 'parent', 'Role': 'Board', 'color': '#71AF17' },
    { 'Id': '1', 'Role': 'General Manager', 'Manager': 'parent', 'ChartType': 'right', 'color': '#71AF17' },
    { 'Id': '11', 'Role': 'Assistant General Manager', 'Manager': '1', 'color': '#71AF17' },
    { 'Id': '2', 'Role': 'Human Resource Manager', 'Manager': '1', 'ChartType': 'right', 'color': '#1859B7' },
    { 'Id': '3', 'Role': 'Trainers', 'Manager': '2', 'color': '#2E95D8' },
    { 'Id': '4', 'Role': 'Recruiting Team', 'Manager': '2', 'color': '#2E95D8' },
    { 'Id': '5', 'Role': 'Finance Asst. Manager', 'Manager': '2', 'color': '#2E95D8' },
    { 'Id': '6', 'Role': 'Design Manager', 'Manager': '1', 'ChartType': 'right', 'color': '#1859B7' },
    { 'Id': '7', 'Role': 'Design Supervisor', 'Manager': '6', 'color': '#2E95D8' },
    { 'Id': '8', 'Role': 'Development Supervisor', 'Manager': '6', 'color': '#2E95D8' },
    { 'Id': '9', 'Role': 'Drafting Supervisor', 'Manager': '6', 'color': '#2E95D8' },
    { 'Id': '10', 'Role': 'Operations Manager', 'Manager': '1', 'ChartType': 'right', 'color': '#1859B7' },
    { 'Id': '11', 'Role': 'Statistics Department', 'Manager': '10', 'color': '#2E95D8' },
    { 'Id': '12', 'Role': 'Logistics Department', 'Manager': '10', 'color': '#2E95D8' },
    { 'Id': '16', 'Role': 'Marketing Manager', 'Manager': '1', 'ChartType': 'right', 'color': '#1859B7' },
    { 'Id': '17', 'Role': 'Overseas Sales Manager', 'Manager': '16', 'color': '#2E95D8' },
    { 'Id': '18', 'Role': 'Petroleum Manager', 'Manager': '16', 'color': '#2E95D8' },
    { 'Id': '20', 'Role': 'Service Department Manager', 'Manager': '16', 'color': '#2E95D8' },
    { 'Id': '21', 'Role': 'Quality Control Department', 'Manager': '16', 'color': '#2E95D8' }
];

const SAMPLE_CSS = `
/* Property panel orientation and sub tree alignment */
.diagram-organization .image-pattern-style {
        background-color: white;
        background-size: contain;
        background-repeat: no-repeat;
        height: 75px;
        width: calc((100% - 18px) / 3);
        cursor: pointer;
        border: 1px solid #D5D5D5;
        background-position: center;
        float: left;
    }

    .diagram-organization .image-pattern-style:hover {
        border-color: gray;
        border-width: 2px;
    }

    .diagram-organization .row {
        margin-left: 0px;
        margin-right: 0px;
    }

    .diagram-organization .row-header {
        font-size: 13px;
        font-weight: 500;
    }

    .diagram-organization .property-panel-header {
      padding-top: 15px;
      padding-bottom: 15px;
    }

    .diagram-organization .e-selected-orientation-style {
        border-color: #006CE6;
        border-width: 2px;
    }

    .diagram-organization .e-selected-pattern-style {
        border-color: #006CE6;
        border-width: 2px;
    }

    .diagram-organization .col-xs-6 {
        padding-left: 0px;
        padding-right: 0px;
    }`;

let diagramInstance: DiagramComponent;
let orientation: LayoutOrientation;
let type: SubTreeAlignments;
let orientationInstance: HTMLElement;
let patternInstance: HTMLElement;

function OrganizationModel() {
  function rendereComplete() {
    //Click Event for orientation of the PropertyPanel.
    orientationInstance.onclick = (args: MouseEvent) => {
      let target: HTMLElement = args.target as HTMLElement;
      let selectedElement: HTMLCollection = document.getElementsByClassName(
        "e-selected-orientation-style"
      );
      if (selectedElement.length) {
        selectedElement[0].classList.remove("e-selected-orientation-style");
      }
      if (!target.classList.contains("e-selected-orientation-style")) {
        target.classList.add("e-selected-orientation-style");
      }
      if (
        target.className === "image-pattern-style e-selected-orientation-style"
      ) {
        switch (target.id) {
          case "toptobottom":
            diagramInstance.layout.orientation = "TopToBottom";
            break;
          case "bottomtotop":
            diagramInstance.layout.orientation = "BottomToTop";
            break;
          case "lefttoright":
            diagramInstance.layout.orientation = "LeftToRight";
            break;
          case "righttoleft":
            diagramInstance.layout.orientation = "RightToLeft";
            break;
          default:
            if (selectedElement.length) {
              selectedElement[0].classList.remove(
                "e-selected-orientation-style"
              );
            }
        }
        diagramInstance.dataBind();
        diagramInstance.doLayout();
      }
    };
    //Click Event for pattern of the PropertyPanel.
    patternInstance.onclick = (args: MouseEvent) => {
      let target: HTMLElement = args.target as HTMLElement;
      let selectedpatternElement: HTMLCollection = document.getElementsByClassName(
        "e-selected-pattern-style"
      );
      if (selectedpatternElement.length) {
        selectedpatternElement[0].classList.remove("e-selected-pattern-style");
      }
      if (!target.classList.contains("e-selected-pattern-style")) {
        target.classList.add("e-selected-pattern-style");
      }
      if (target.className === "image-pattern-style e-selected-pattern-style") {
        switch (target.id) {
          case "pattern1":
            orientation = "Vertical".toString() as LayoutOrientation;
            type = "Alternate" as SubTreeAlignments;
            break;
          case "pattern2":
            orientation = "Vertical".toString() as LayoutOrientation;
            type = "Left" as SubTreeAlignments;
            break;
          case "pattern3":
            orientation = "Vertical".toString() as LayoutOrientation;
            type = "Left" as SubTreeAlignments;
            break;
          case "pattern4":
            orientation = "Vertical".toString() as LayoutOrientation;
            type = "Right" as SubTreeAlignments;
            break;
          case "pattern5":
            orientation = "Vertical".toString() as LayoutOrientation;
            type = "Right" as SubTreeAlignments;
            break;
          case "pattern6":
            orientation = "Horizontal".toString() as LayoutOrientation;
            type = "Balanced" as SubTreeAlignments;
            break;
          case "pattern7":
            orientation = "Horizontal".toString() as LayoutOrientation;
            type = "Center" as SubTreeAlignments;
            break;
          case "pattern8":
            orientation = "Horizontal".toString() as LayoutOrientation;
            type = "Left" as SubTreeAlignments;
            break;
          case "pattern9":
            orientation = "Horizontal".toString() as LayoutOrientation;
            type = "Right" as SubTreeAlignments;
            break;
          default:
            if (selectedpatternElement.length) {
              selectedpatternElement[0].classList.remove(
                "e-selected-pattern-style"
              );
            }
        }
        diagramInstance.layout.getLayoutInfo = (
          node: Node,
          options: TreeInfo
        ) => {
          if (target.id === "pattern4" || target.id === "pattern3") {
            options.offset = -50;
          }
          if (orientation) {
            getLayoutInfo(node, options, orientation, type);
          }
        };

        diagramInstance.dataBind();
        diagramInstance.doLayout();
      }
    };
  }
  //set orientation and type of the Layout.
  function getLayoutInfo(
    node: Node,
    options: TreeInfo,
    orientation: LayoutOrientation,
    type: SubTreeAlignments
  ): void {
    /* tslint:disable:no-string-literal */
    if ((node.data as DataInfo)["Role"] === "General Manager") {
      options.assistants.push(options.children[0]);
      options.children.splice(0, 1);
    }
    if (!options.hasSubTree) {
      options.orientation = orientation as SubTreeOrientation;
      options.type = type;
    }
  }

  //sets default value for Node.
  function nodeDefaults(obj: Node, diagram: Diagram): Node {
    obj.backgroundColor = (obj.data as EmployeeInfo).color;
    obj.style = { fill: "none", strokeColor: "none", color: "white" };
    obj.expandIcon = {
      height: 10,
      width: 10,
      shape: "None",
      fill: "lightgray",
      offset: { x: 0.5, y: 1 }
    };
    obj.expandIcon.verticalAlignment = "Center";
    obj.expandIcon.margin = { left: 0, right: 0, top: 0, bottom: 0 };
    obj.collapseIcon = { height: 10, width: 10, shape: "None", fill: "lightgray", offset: { x: 0.5, y: 1 } };
    obj.collapseIcon.verticalAlignment = "Center";
    obj.collapseIcon.margin = { left: 0, right: 0, top: 0, bottom: 0 };
    obj.width = 120;
    obj.height = 30;
    return obj;
  }

  //sets default value for Connector.
  function connectorDefaults(
    connector: ConnectorModel,
    diagram: Diagram
  ): ConnectorModel {
    connector.targetDecorator.shape = "None";
    connector.type = "Orthogonal";
    connector.constraints = ConnectorConstraints.None;
    connector.cornerRadius = 0;
    return connector;
  }
  // Updates expand and collapse icons of nodes based on args.checked state
  function onExpandChange (args : ChangeEventArgs): void {
    for (let node of diagramInstance.nodes) {
        if (args.checked) {
            node.expandIcon.shape = 'Minus';
            node.collapseIcon.shape = 'Plus';
        } else {
            node.expandIcon.shape = 'None';
            node.collapseIcon.shape = 'None';
        }
    }
    diagramInstance.dataBind();
    diagramInstance.doLayout();
  }; 
  return (
    <div className="control-pane diagram-organization">
      <style>{SAMPLE_CSS}</style>
      <div className="col-lg-8 control-section">
        <div  style={{ width: "100%" }}>
          <DiagramComponent
            id="diagram"
            ref={(diagram) => (diagramInstance = diagram)}
            width={"100%"}
            height={"700px"}
            snapSettings={{ constraints: SnapConstraints.None }}
            //configures data source settings
            dataSourceSettings={{
              id: "Id",
              parentId: "Manager",
              dataSource: new DataManager(localBindData as JSON[]),
              doBinding: (
                nodeModel: NodeModel,
                data: object,
                diagram: Diagram
              ) => {
                nodeModel.shape = {
                  type: "Text",
                  content: (data as EmployeeInfo).Role,
                  margin: { left: 10, right: 10, top: 10, bottom: 10 },
                };
              },
            }}
            //Disables all interactions except zoom/pan
            tool={DiagramTools.ZoomPan}
            //Configures automatic layout
            layout={{
              type: "OrganizationalChart",
              getLayoutInfo: (node: Node, options: TreeInfo) => {
                /* tslint:disable:no-string-literal */
                if ((node.data as DataInfo)["Role"] === "General Manager") {
                  options.assistants.push(options.children[0]);
                  options.children.splice(0, 1);
                }
                if (!options.hasSubTree) {
                  options.type = "Right";
                }
              },
            }}
            //Defines the default node and connector properties
            getNodeDefaults={(obj: Node, diagram: Diagram) => {
              /* tslint:disable:no-string-literal */
              return nodeDefaults(obj, diagram);
            }}
            getConnectorDefaults={(
              connector: ConnectorModel,
              diagram: Diagram
            ) => {
              return connectorDefaults(connector, diagram);
            }}
          >
            <Inject
              services={[DataBinding, HierarchicalTree, LayoutAnimation]}
            />
          </DiagramComponent>
        </div>
      </div>

    </div>
  );
}
export interface DataInfo {
  [key: string]: string;
}
export default OrganizationModel;
```
