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

Node fundamentals

Before creating nodes, understanding their core properties helps in effective diagram development:

  • Position: Defined by offsetX and offsetY properties for precise placement
  • Size: Controlled through width and height properties
  • Identification: Each node requires a unique id for 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 dataBind method 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.

See Also