# diagram-organization-chart

> Organizational chart diagram with switchable subtree alignments, spacing controls, and animations.

**Framework:** angular  **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/angular/diagram-organization-chart.json
```

**Install Package(s)**

```bash
npm install @syncfusion/ej2-angular-diagrams
```

**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/organization-chart.component.ts

```typescript
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { ChangeEventArgs as NumericChangeEventArgs } from '@syncfusion/ej2-inputs';
import { DiagramComponent, Diagram, NodeModel, ConnectorModel, LayoutOrientation, LayoutAnimation, TreeInfo, SnapSettingsModel, SubTreeOrientation, SubTreeAlignments, DiagramTools, Node, DataBinding, HierarchicalTree, ConnectorConstraints, SnapConstraints, DiagramModule } from '@syncfusion/ej2-angular-diagrams';
import { DataManager } from '@syncfusion/ej2-data';
import { localBindData } from '../diagram-data';
import { NumericTextBoxModule } from '@syncfusion/ej2-angular-inputs';
import { CheckBoxModule, ChangeEventArgs } from '@syncfusion/ej2-angular-buttons';
Diagram.Inject(DataBinding, HierarchicalTree, LayoutAnimation);

export interface EmployeeInfo {
    Role: string;
    color: string;
}
export interface DataInfo {
    [key: string]: string;
}

/**
 * Sample for Organizational Chart
 */
@Component({
    selector: 'control-content',
    templateUrl: 'organization-chart.html',
    encapsulation: ViewEncapsulation.None,
    standalone: true,
    imports: [ DiagramModule, NumericTextBoxModule, CheckBoxModule]
})
export class OrganizationalChartDiagramComponent {
    @ViewChild('diagram')
    public diagram: DiagramComponent | undefined;
    public snapSettings: SnapSettingsModel = { constraints: SnapConstraints.None };
    public tool: DiagramTools = DiagramTools.ZoomPan;
    //configures data
    public data: Object = {
        id: 'Id', parentId: 'Manager',
        dataSource: new DataManager(localBindData),
        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 }
            };
        }
    };
    //Configures automatic layout
    public layout: Object = {
        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
    public nodeDefaults(obj: NodeModel): NodeModel {
        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: .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: .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;
    };
    public connectorDefaults(connector: any, diagram: Diagram): ConnectorModel {
        connector.targetDecorator.shape = 'None';
        connector.type = 'Orthogonal';
        connector.constraints = ConnectorConstraints.None;;
        connector.cornerRadius = 0;
        return connector;
    }
    ngOnInit(): void {
        document.getElementById('pattern')!.onclick = this.documentClick.bind(this);
        document.getElementById('orientation')!.onclick = this.orientation.bind(this);
    }
     //To change orientation
     private orientation(args: any) {
        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'
        ) {
          let id: string = target.id;
          let orientation1: string =
            id.substring(0, 1).toUpperCase() + id.substring(1, id.length);
          this.diagram!.layout.orientation = orientation1 as LayoutOrientation;
          this.diagram!.dataBind();
          this.diagram!.doLayout();
        }
      }
    //To change subtree alignment
    private documentClick(args: MouseEvent): void {
        let target: HTMLElement = args.target as HTMLElement;
        var selectedpatternElement = 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') {
          let subTreeOrientation: SubTreeOrientation;
          let subTreeAlignment: SubTreeAlignments;
          switch (target.id) {
            case 'pattern1':
              subTreeOrientation = 'Vertical';
              subTreeAlignment = 'Alternate';
              break;
            case 'pattern2':
              subTreeOrientation = 'Vertical';
              subTreeAlignment = 'Left';
              break;
            case 'pattern3':
              subTreeOrientation = 'Vertical';
              subTreeAlignment = 'Left';
              break;
              case 'pattern4':
              subTreeOrientation = 'Vertical';
              subTreeAlignment = 'Right';
              break;
            case 'pattern5':
              subTreeOrientation = 'Vertical';
              subTreeAlignment = 'Right';
              break;
            case 'pattern6':
              subTreeOrientation = 'Horizontal';
              subTreeAlignment = 'Balanced';
              break;
            case 'pattern7':
              subTreeOrientation = 'Horizontal';
              subTreeAlignment = 'Center';
              break;
            case 'pattern8':
              subTreeOrientation = 'Horizontal';
              subTreeAlignment = 'Left';
              break;
            case 'pattern9':
              subTreeOrientation = 'Horizontal';
              subTreeAlignment = 'Right';
              break;
          }

          this.diagram!.layout.getLayoutInfo = (
            node: NodeModel,
            options: TreeInfo
          ) => {
            if (target.id === 'pattern4' || target.id === 'pattern3') {
              options.offset = -50;
            }
            if ((node.data as DataInfo)['Role'] === 'General Manager') {
              options.assistants!.push(options.children![0]);
              options.children!.splice(0, 1);
            }
            if (!options.hasSubTree) {
              options.orientation = subTreeOrientation;
              options.type = subTreeAlignment;
            }
          };
          this.diagram!.dataBind();
          this.diagram!.doLayout();
        }
      }
    //To change horizontal spacing
    public onHorizontalSpacingChange(args: NumericChangeEventArgs): void {
        this.diagram!.layout.horizontalSpacing = Number(args.value);
        this.diagram!.dataBind();
    }
    //To change vertical spacing
    public onVerticalSpacingChange(args: NumericChangeEventArgs): void {
        this.diagram!.layout.verticalSpacing = Number(args.value);
        this.diagram!.dataBind();
    }
    // Function to enable expand and collapse icon
    public onExpandChange(args: ChangeEventArgs): void {
        for (let node of this.diagram!.nodes) {
            if (args.checked) {
                node.expandIcon!.shape = 'Minus';
                node.collapseIcon!.shape = 'Plus';
            } else {
                node.expandIcon!.shape = 'None';
                node.collapseIcon!.shape = 'None';
            }
        }
        this.diagram!.dataBind();
        this.diagram!.doLayout();
    }

}
```

### src/components/diagram-organization-chart/organization-chart.html

```html
<style>
    .diagram-organizationalchart .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-organizationalchart .row {
        margin-left: 0px;
        margin-right: 0px;
    }

    .diagram-organizationalchart .row-header {
        font-size: 15px;
        font-weight: 500;
    }

    .diagram-organizationalchart .sb-child-row {
        padding-top: 8px;
    }

    .diagram-organizationalchart .e-selected-orientation-style {
        border-color: #006CE6;
        border-width: 2px;
    }
    .diagram-organizationalchart .e-selected-pattern-style {
       border-color: #006CE6;
       border-width: 2px;
   }
   .diagram-organizationalchart .image-pattern-style:hover {
            border-color: gray;
            border-width: 2px;
        }

    .diagram-organizationalchart .col-xs-6 {
        padding-left: 0px;
        padding-right: 0px;
    }

    .diagram-organizationalchart .sample-border {
        border-right: 1px solid #D5D5D5;
    }
</style>

<div class="control-section diagram-organizationalchart" style="padding-top: 0px;">
    <div class="col-lg-8 control-section sample-border">
        <div class="content-wrapper">
            <ejs-diagram #diagram id="diagram" width="100%" height="700px" [getConnectorDefaults]='connectorDefaults' [getNodeDefaults]='nodeDefaults' [layout]='layout' [dataSourceSettings]='data' [tool]='tool' [snapSettings]='snapSettings'>
            </ejs-diagram>
        </div>
    </div>
    <div class="col-lg-4 property-section">
        <div class="property-panel-header">
            Properties
        </div>
        <div class="row property-panel-content" id="appearance">
            <div class="row" style="padding-top: 10px">
                <div class="row row-header sb-child-row">
                    Orientation
                </div>
                <div id="orientation">
                <div class="row sb-child-row">
                    <div class="image-pattern-style e-selected-orientation-style" id="topToBottom" style="background-image: url(https://ej2.syncfusion.com/angular/demos/assets/diagram/Images/common-orientation/toptobottom.png); margin-right: 3px">
                    </div>
                    <div class="image-pattern-style" id="bottomToTop" style="background-image: url(https://ej2.syncfusion.com/angular/demos/assets/diagram/Images/common-orientation/bottomtotop.png); margin: 0px 3px">
                    </div>
                    <div class="image-pattern-style" id="leftToRight" style="background-image: url(https://ej2.syncfusion.com/angular/demos/assets/diagram/Images/common-orientation/lefttoright.png); margin-left: 3px">
                    </div>
                </div>
                <div class="row sb-child-row">
                    <div class="image-pattern-style" id="rightToLeft" style="background-image: url(https://ej2.syncfusion.com/angular/demos/assets/diagram/Images/common-orientation/righttoleft.png);">
                    </div>
                </div>
                </div>
                <div class="row row-header sb-child-row">
                    Subtree Alignment
                </div>
                <div id="pattern">
                <div class="row sb-child-row">
                    <div class="image-pattern-style" id="pattern1" style="background-image: url(https://ej2.syncfusion.com/angular/demos/assets/diagram/patternimages/Pattern_1.png); margin-right: 3px">
                    </div>
                    <div class="image-pattern-style" id="pattern2" style="background-image: url(https://ej2.syncfusion.com/angular/demos/assets/diagram/patternimages/Pattern_2.png); margin: 0px 3px">
                    </div>
                    <div class="image-pattern-style" id="pattern3" style="background-image: url(https://ej2.syncfusion.com/angular/demos/assets/diagram/patternimages/Pattern_3.png); margin: 0px 3px">
                    </div>
                </div>
                <div class="row sb-child-row">
                    <div class="image-pattern-style" id="pattern4" style="background-image: url(https://ej2.syncfusion.com/angular/demos/assets/diagram/patternimages/Pattern_4.png); margin-right: 3px">
                    </div>
                    <div class="image-pattern-style e-selected-pattern-style" id="pattern5" style="background-image: url(https://ej2.syncfusion.com/angular/demos/assets/diagram/patternimages/Pattern_5.png); margin: 0px 3px">
                    </div>
                    <div class="image-pattern-style" id="pattern6" style="background-image: url(https://ej2.syncfusion.com/angular/demos/assets/diagram/patternimages/Pattern_6.png); margin: 0px 3px">
                    </div>
                </div>
                <div class="row sb-child-row">
                    <div class="image-pattern-style" id="pattern7" style="background-image: url(https://ej2.syncfusion.com/angular/demos/assets/diagram/patternimages/Pattern_7.png); margin-right: 3px">
                    </div>
                    <div class="image-pattern-style" id="pattern8" style="background-image: url(https://ej2.syncfusion.com/angular/demos/assets/diagram/patternimages/Pattern_8.png); margin: 0px 3px">
                    </div>
                    <div class="image-pattern-style" id="pattern9" style="background-image: url(https://ej2.syncfusion.com/angular/demos/assets/diagram/patternimages/Pattern_9.png); margin: 0px 3px">
                    </div>
                </div>
            </div>
            </div>
        </div>
        <div class="row property-panel-content" style="padding-top: 10px">
            <div class="row row-header sb-child-row">
                Behavior
            </div>
            <div class="row sb-child-row">
                <div style="display: table;height: 35px;" class="col-xs-6">
                    <div style="display: table-cell; vertical-align: middle">Horizontal Spacing</div>
                </div>
                <div class="col-xs-6">
                    <ejs-numerictextbox id='horizontalSpace' min="20" max="60" format='###.##' step="2" value="30" (change)='onHorizontalSpacingChange($event)'></ejs-numerictextbox>
                </div>
            </div>
            <div class="row sb-child-row">
                <div style="display: table;height: 35px;" class="col-xs-6">
                    <div style="display: table-cell; vertical-align: middle">Vertical Spacing</div>
                </div>
                <div class="col-xs-6">
                    <ejs-numerictextbox id='verticalSpacing' min="20" max="60" format='###.##' step="2" value="30" (change)='onVerticalSpacingChange($event)'></ejs-numerictextbox>
                </div>
            </div>
            <div class="row sb-child-row" style="display: none;">
                <ejs-checkbox label="Expandable" [checked]="false" (change)="onExpandChange($event)"></ejs-checkbox>
            </div>
        </div>
    </div>
</div>
```
