Nodes in Angular Diagram Component
29 Aug 202522 minutes to read
Nodes are graphical objects that visually represent entities, processes, data flow, or any business logic within diagrams. They serve as the fundamental building blocks for creating flowcharts, organizational charts, network diagrams, and other visual representations. Each node can be customized with different shapes, sizes, colors, and interactive behaviors to suit specific diagram requirements.

Node fundamentals
Before creating nodes, understanding their core properties helps in effective diagram development:
- 
Position: Defined by offsetXandoffsetYproperties for precise placement
- 
Size: Controlled through widthandheightproperties
- 
Identification: Each node requires a unique idfor runtime operations
- Stacking: Nodes are layered from bottom to top based on addition order
Creating nodes
Add nodes through nodes collection
To create a node, define the node object and add it to the nodes collection of the diagram model. The id property serves as the unique identifier for runtime operations and customization.
import {
    DiagramModule,
    DiagramComponent,
    NodeModel,
    ShapeStyleModel,
  } from '@syncfusion/ej2-angular-diagrams';
  
  import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
  
  @Component({
    imports: [DiagramModule],
  
    providers: [],
    standalone: true,
    selector: 'app-container',
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" [getNodeDefaults] ='getNodeDefaults'>
          <e-nodes>
              <e-node id='node1' [offsetX]=150 [offsetY]=150></e-node>
          </e-nodes>
      </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None,
  })
  export class AppComponent {
    @ViewChild('diagram')
    public diagram?: DiagramComponent;
    public getNodeDefaults(node: NodeModel): NodeModel {
      node.height = 100;
      node.width = 100;
      return node;
    }
  }import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));NOTE
Node ID must begin with a letter, remain unique across all shapes and connectors, and avoid whitespace or special characters.
Create nodes from data source
Nodes can be generated automatically using the dataSource property. Default properties for these nodes are retrieved from getNodeDefaults settings. For detailed information about data binding, refer to DataBinding.
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import {
  DataSourceModel,
  DiagramComponent,
  DiagramModule,
  Diagram,
  NodeModel,
  DataBinding,
} from '@syncfusion/ej2-angular-diagrams';
import { DataManager, Query } from '@syncfusion/ej2-data';
Diagram.Inject(DataBinding);
@Component({
  imports: [DiagramModule],
  providers: [],
  standalone: true,
  selector: 'app-container',
  template: `<ejs-diagram #diagram id="diagram" width="100%" height="1000px" [getNodeDefaults] ='getNodeDefaults' [dataSourceSettings]="dataSourceSettings">
      </ejs-diagram>`,
  encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
  @ViewChild('diagram')
  public diagram?: DiagramComponent;
  public dataSourceSettings?: DataSourceModel;
  public items?: DataManager;
  public data: Object[] = [
    {
      id: 'Steve-Ceo',
      parent: null,
    },
  ];
  public getNodeDefaults(node: NodeModel): NodeModel {
    node.height = 100;
    node.width = 100;
    node.offsetX = 300;
    node.offsetY = 200;
    node.style = { fill: 'yellow', strokeColor: 'yellow' };
    return node;
  }
  ngOnInit(): void {
    this.items = new DataManager(this.data as JSON[], new Query().take(7));
    this.dataSourceSettings = {
      id: 'id',
      parentId: 'parent',
      dataSource: this.items,
    };
  }
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Add nodes from symbol palette
Nodes can be predefined in a symbol palette and dragged into the diagram as needed. This approach provides users with a library of reusable components. For comprehensive guidance on symbol palette integration, refer to Symbol Palette.
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import {
  DiagramComponent,
  DiagramModule,
  ShapeStyleModel,
  SymbolPaletteModule,
  NodeModel,
  PaletteModel,
} from '@syncfusion/ej2-angular-diagrams';
@Component({
  imports: [DiagramModule, SymbolPaletteModule],
  providers: [],
  standalone: true,
  selector: 'app-container',
  template: `
      <ejs-symbolpalette id="symbolpalette"width="10%" height="700px" [palettes]="palettes" [symbolHeight]=80 [symbolWidth]=80 >
      </ejs-symbolpalette>
      <ejs-diagram #diagram id="diagram" width="74%" height="700px" [getNodeDefaults] ='getNodeDefaults'>
          <e-nodes>
              <e-node id='node1' [offsetX]=150 [offsetY]=150></e-node>
          </e-nodes>
      </ejs-diagram>`,
  encapsulation: ViewEncapsulation.None,
  styles: [
    `
      ejs-symbolpalette {
      float: left;
    }
  `,
  ],
})
export class AppComponent {
  @ViewChild('diagram')
  public diagram?: DiagramComponent;
  public getNodeDefaults(node: NodeModel): NodeModel {
    node.height = 100;
    node.width = 100;
    return node;
  }
  public palettes?: PaletteModel[];
  public getBasicShapes(): NodeModel[] {
    let basicShapes: NodeModel[] = [
      {
        id: 'Rectangle',
        shape: {
          type: 'Basic',
          shape: 'Rectangle',
        },
        style: { fill: '#6BA5D7' },
      },
    ];
    return basicShapes;
  }
  ngOnInit(): void {
    this.palettes = [
      {
        id: 'basic',
        expanded: true,
        symbols: this.getBasicShapes(),
        title: 'Basic Shapes',
        iconCss: 'e-ddb-icons e-basic',
      },
    ];
  }
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Draw nodes interactively
To enable interactive node drawing, activate the drawing tool by setting DrawOnce or ContinuousDraw to the tool property and configure the node template using the drawingObject property.
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import {
  DiagramModule,
  DiagramComponent,
  Diagram,
  NodeModel,
  BasicShapeModel,
  DiagramTools,
} from '@syncfusion/ej2-angular-diagrams';
@Component({
  imports: [DiagramModule],
  providers: [],
  standalone: true,
  selector: 'app-container',
  template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" (created)='created($event)'>
    </ejs-diagram>`,
  encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
  @ViewChild('diagram')
  public diagram?: DiagramComponent;
  public drawingshape?: BasicShapeModel;
  public node?: NodeModel;
  public created(args: Object): void {
    //JSON to create a rectangle
    this.drawingshape = { type: 'Basic', shape: 'Rectangle' };
    this.node = {
      shape: this.drawingshape,
    };
    (this.diagram as Diagram).drawingObject = this.node;
    //To draw an object once, activate draw once
    (this.diagram as Diagram).tool = DiagramTools.DrawOnce;
    (this.diagram as Diagram).dataBind();
  }
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Runtime node operations
Add and remove individual nodes
Nodes can be dynamically added using the add method and removed using the remove method. Both operations trigger the collectionChange event, allowing for custom handling of diagram modifications.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { DiagramModule } from '@syncfusion/ej2-angular-diagrams'
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, NodeModel } from '@syncfusion/ej2-angular-diagrams';
@Component({
imports: [
         DiagramModule
    ],
providers: [ ],
standalone: true,
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" (created)='created($event)'>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public node: NodeModel = {
        // Position of the node
        offsetX: 250,
        offsetY: 250,
        // Size of the node
        width: 100,
        height: 100,
        style: {
            fill: '#6BA5D7',
            strokeColor: 'white'
        },
    };
    public created(args: Object): void {
        //Add Node
        (this.diagram as Diagram).add(this.node);
    }
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Add multiple nodes simultaneously
Collections of nodes can be efficiently added using the addElements method. This approach is optimal for bulk operations and triggers the collectionChange event for each added element.
import { DiagramModule, DiagramComponent, Diagram, NodeModel } from '@syncfusion/ej2-angular-diagrams'
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
@Component({
imports: [
         DiagramModule
    ],
providers: [ ],
standalone: true,
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" (created)='created($event)'>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public node: NodeModel =[
        { id: 'node16', offsetX: 35, offsetY: 260 },
        { id: 'node17', offsetX: 140, offsetY: 260 },
        { id: 'node18', offsetX: 240, offsetY: 260 }] as NodeModel;
        public created(args: Object): void {
            //Add Nodes collection
            (this.diagram as Diagram).addElements(this.node as any);
        }
    }import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Update node properties
Node properties can be modified at runtime with immediate visual updates. Changes take effect instantly, allowing for dynamic diagram manipulation based on user interactions or data updates.
import {
  DiagramModule,
  ShapeStyleModel,
  DiagramComponent,
  Diagram,
  NodeModel,
} from '@syncfusion/ej2-angular-diagrams';
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
@Component({
  imports: [DiagramModule],
  providers: [],
  standalone: true,
  selector: 'app-container',
  template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" [nodes]="nodes" >
    </ejs-diagram>
    <button (click) = "ChangeColor()">Change Color</button>
    <button (click) = "ChangeSize()">Change Size</button>`,
  styles: [
    `button {
      margin-left: 10px;
    }`,
  ],
  encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
  public nodes: NodeModel[] = [
    {
      id: 'node1',
      offsetX: 420,
      offsetY: 270,
      height: 100,
      width: 100,
      style: { fill: '#6AA8D7', strokeWidth: 1 },
    },
  ];
  @ViewChild('diagram')
  public diagram?: DiagramComponent;
  ChangeColor() {
    if (
      ((this.diagram as Diagram).nodes[0].style as ShapeStyleModel).fill ==
      'orange'
    ) {
      ((this.diagram as Diagram).nodes[0].style as ShapeStyleModel).fill =
        '#6AA8D7';
    } else {
      ((this.diagram as Diagram).nodes[0].style as ShapeStyleModel).fill =
        'orange';
    }
  }
  ChangeSize() {
    if (
      (this.diagram as Diagram).nodes[0].width == 200 &&
      (this.diagram as Diagram).nodes[0].height == 200
    ) {
      (this.diagram as Diagram).nodes[0].width = 100;
      (this.diagram as Diagram).nodes[0].height = 100;
    } else {
      (this.diagram as Diagram).nodes[0].width = 200;
      (this.diagram as Diagram).nodes[0].height = 200;
    }
  }
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));NOTE
Call the
dataBindmethod after property updates to ensure immediate reflection of changes.
Clone nodes
Node cloning creates new instances with identical properties and attributes. Use the copy and paste methods to duplicate existing nodes programmatically.
import {
  DiagramModule,
  DiagramComponent,
  NodeModel,
} from '@syncfusion/ej2-angular-diagrams';
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
@Component({
  imports: [DiagramModule],
  providers: [],
  standalone: true,
  selector: 'app-container',
  template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" [nodes]="nodes" >
    </ejs-diagram>
    <button (click) = "CloneNode()">Clone Node</button>`,
  styles: [
    `button {
      margin-left: 10px;
    }`,
  ],
  encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
  public nodes: NodeModel[] = [
    {
      id: 'node1',
      offsetX: 420,
      offsetY: 270,
      height: 100,
      width: 100,
      style: { fill: '#6AA8D7', strokeWidth: 1 },
    },
  ];
  @ViewChild('diagram')
  public diagram?: DiagramComponent;
  public selectedNode?: NodeModel;
  CloneNode() {
    this.selectedNode =
      ((this.diagram as DiagramComponent).selectedItems.nodes
        ?.length as number) > 0
        ? (
            (this.diagram as DiagramComponent).selectedItems
              .nodes as NodeModel[]
          )[0]
        : (this.diagram as DiagramComponent).nodes[0];
    (this.diagram as DiagramComponent).select([this.selectedNode]);
    (this.diagram as DiagramComponent).copy();
    (this.diagram as DiagramComponent).paste();
  }
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Advanced node integration
Import nodes from external components
Custom dragEnter functionality enables conversion of elements from other components, such as tree views, into diagram nodes based on the dragged element’s data properties.