Node Interaction Events in Angular Diagram Component

29 Aug 202520 minutes to read

The Angular Diagram component provides comprehensive event support for node interactions, allowing developers to respond to user actions and customize behavior during various interaction scenarios. These events are triggered when users interact with nodes through clicking, dragging, resizing, rotating, and other operations.

Click Event

Triggered when a user clicks on a node. This event provides access to the clicked node and mouse event details, enabling custom click handling and node-specific actions.

The following code example demonstrates how to handle the click event in the diagram:

import {
  Connector,
  DiagramModule,
  IClickEventArgs,
  PointModel,
  DiagramComponent,
  Node,
  NodeModel,
} from '@syncfusion/ej2-angular-diagrams';
import { Component, ViewEncapsulation, OnInit, 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'  (click)="click($event)">
        <e-nodes>
            <e-node id='node1' [offsetX]=350 [offsetY]=250>
            </e-node>
        </e-nodes>
        <e-connectors>
            <e-connector id='connector' type='Straight' sourceID='node1' [targetPoint]='targetPoint'>
            </e-connector>
        </e-connectors>
    </ejs-diagram>`,
  encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
  @ViewChild('diagram')
  public diagram?: DiagramComponent;
  public targetPoint?: PointModel;
  ngOnInit(): void {
    this.targetPoint = { x: 350, y: 500 };
  }
  public click(args: IClickEventArgs): void {
    if (args.actualObject instanceof Node) {
      alert('Node is clicked');
    } else if (args.actualObject instanceof Connector) {
      alert('Connector is clicked');
    }
  }
  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));

Selection Change Event

Triggered when a node’s selection state changes, either when selected or deselected. This event fires during both the selection process and completion, providing control over selection behavior.

The following code example shows how to handle the selectionChange event:

import {
  DiagramModule,
  ISelectionChangeEventArgs,
  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" [getNodeDefaults] ='getNodeDefaults'  (selectionChange)="selectionChange($event)">
        <e-nodes>
            <e-node id='node1' [offsetX]=350 [offsetY]=250>
            </e-node>
        </e-nodes>
    </ejs-diagram>`,
  encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
  @ViewChild('diagram')
  public diagram?: DiagramComponent;
  public selectionChange(args: ISelectionChangeEventArgs): void {
    if (args.state === 'Changed') {
      console.log('Selection Change');
    }
  }
  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));

Selection can be prevented by setting the cancel property of SelectionChangeEventArgs to true, as shown in the following code:

public selectionChange(args: ISelectionChangeEventArgs): void {
    if (args.state === 'Changing') {
        // Prevents node selection
        args.cancel = true;
    }
}

Position Change Event

Triggered during node dragging operations, providing real-time position updates as users move nodes. This event enables position validation, snap-to-grid functionality, and custom drag behavior.

The following code example demonstrates how to handle the positionChange event:

import {
  DiagramModule,
  IDraggingEventArgs,
  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" [getNodeDefaults] ='getNodeDefaults'  (positionChange)="positionChange($event)">
        <e-nodes>
            <e-node id='node1' [offsetX]=350 [offsetY]=250>
            </e-node>
        </e-nodes>
    </ejs-diagram>`,
  encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
  @ViewChild('diagram')
  public diagram?: DiagramComponent;
  public positionChange(args: IDraggingEventArgs): void {
    if (args.state === 'Completed') {
      console.log('Position Change');
    }
  }
  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));

Dragging can be prevented by setting the cancel property of DraggingEventArgs to true:

public positionChange(args: IDraggingEventArgs): void {
    if (args.state === 'Progress') {
        // Prevents node dragging
        args.cancel = true;
    }
}

Size Change Event

Triggered during node resizing operations when users interact with resize handles. This event provides access to the new dimensions and allows for size constraints and validation.

The following code example shows how to handle the sizeChange event:

import {
  DiagramModule,
  ISizeChangeEventArgs,
  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" [getNodeDefaults] ='getNodeDefaults'  (sizeChange)="sizeChange($event)">
          <e-nodes>
              <e-node id='node1' [offsetX]=350 [offsetY]=250>
              </e-node>
          </e-nodes>
      </ejs-diagram>`,
  encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
  @ViewChild('diagram')
  public diagram?: DiagramComponent;
  public sizeChange(args: ISizeChangeEventArgs): void {
    if (args.state === 'Completed') {
      console.log('Size Change');
    }
  }
  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));

Resizing can be prevented by setting the cancel property of SizeChangeEventArgs to true:

public sizeChange(args: ISizeChangeEventArgs): void {
    if (args.state === 'Progress') {
        // Prevents node resizing
        args.cancel = true;
    }
}

Rotate Change Event

Triggered during node rotation operations when users interact with the rotation handle. This event enables rotation constraints and custom rotation behavior.

The following code example demonstrates how to handle the rotateChange event:

import {
  DiagramModule,
  IRotationEventArgs,
  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" [getNodeDefaults] ='getNodeDefaults'  (rotateChange)="rotateChange($event)">
          <e-nodes>
              <e-node id='node1' [offsetX]=350 [offsetY]=250>
              </e-node>
          </e-nodes>
      </ejs-diagram>`,
  encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
  @ViewChild('diagram')
  public diagram?: DiagramComponent;
  public rotateChange(args: IRotationEventArgs): void {
    if (args.state === 'Completed') {
      console.log('Rotate Change');
    }
  }
  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));

Rotation can be prevented by setting the cancel property of RotationEventArgs to true:

public rotateChange(args: IRotationEventArgs): void {
    if (args.state === 'Progress') {
        // Prevents node rotation
        args.cancel = true;
    }
}

Property Change Event

Triggered when any property of a node is modified programmatically or through user interaction. This event is useful for tracking changes and implementing custom validation logic.

The following code example shows how to handle the propertyChange event:

import {
  DiagramModule,
  IPropertyChangeEventArgs,
  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" [getNodeDefaults] ='getNodeDefaults'  (propertyChange)="propertyChange($event)">
          <e-nodes>
              <e-node id='node1' [offsetX]=350 [offsetY]=250>
              </e-node>
          </e-nodes>
      </ejs-diagram>`,
  encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
  @ViewChild('diagram')
  public diagram?: DiagramComponent;
  public propertyChange(args: IPropertyChangeEventArgs): void {
    console.log(args.newValue);
  }
  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));

Collection Change Event

Triggered when nodes are added to or removed from the diagram dynamically. This event provides control over diagram modifications and enables validation before collection changes occur.

The following code example demonstrates how to handle the collectionChange event:

import {
  DiagramModule,
  ICollectionChangeEventArgs,
  DiagramComponent,
  NodeModel,
} from '@syncfusion/ej2-angular-diagrams';

import { Component, ViewEncapsulation, ViewChild } from '@angular/core';

@Component({
  imports: [DiagramModule],

  providers: [],
  standalone: true,
  selector: 'app-container',
  template: `<button (click)= 'add()'>Add</button>
    <ejs-diagram #diagram id="diagram" width="100%" height="580px" [getNodeDefaults] ='getNodeDefaults'  (collectionChange)="collectionChange($event)">
          <e-nodes>
              <e-node id='node1' [offsetX]=350 [offsetY]=250>
              </e-node>
          </e-nodes>
      </ejs-diagram>`,
  encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
  @ViewChild('diagram')
  public diagram?: DiagramComponent;
  public node: NodeModel = {
    // Position of the node
    offsetX: 500,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
    style: {
      fill: 'skyblue',
    },
  };
  public collectionChange(args: ICollectionChangeEventArgs): void {
    if (args.state === 'Changed') {
      console.log('Collection Change');
    }
  }
  public add() {
    (this.diagram as any).add(this.node);
  }
  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));

Collection changes can be prevented by setting the cancel property of CollectionChangeEventArgs to true:

public collectionChange(args: ICollectionChangeEventArgs): void {
    if (args.state === 'Changing') {
        // Prevents adding or removing nodes from the diagram
        args.cancel = true;
    }
}

Mouse Events

The diagram component provides mouse interaction events that trigger when users hover over or move the mouse cursor in relation to node surfaces.

Mouse Enter Event

The mouseEnter event is triggered when the mouse cursor enters a node’s boundary area.

Mouse Over Event

The mouseOver event is triggered when the mouse cursor hovers over a node’s surface area.

Mouse Leave Event

The mouseLeave event is triggered when the mouse cursor leaves a node’s boundary area.

The following code example demonstrates how to handle these mouse events and implement visual feedback by changing node colors based on mouse interactions:

import {
  DiagramModule,
  IMouseEventArgs,
  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" [getNodeDefaults] ='getNodeDefaults'  (mouseEnter)="mouseEnter($event)" (mouseLeave)="mouseLeave($event)" (mouseOver)="mouseOver($event)">
          <e-nodes>
              <e-node id='node1' [offsetX]=350 [offsetY]=250>
              </e-node>
          </e-nodes>
      </ejs-diagram>`,
  encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
  @ViewChild('diagram')
  public diagram?: DiagramComponent;
  public mouseEnter(args: IMouseEventArgs): void {
    (args.actualObject as any).style.fill = 'red';
    (this.diagram as any).dataBind();
  }

  public mouseLeave(args: IMouseEventArgs): void {
    (args.element as any).style.fill = 'skyblue';
    (this.diagram as any).dataBind();
  }

  public mouseOver(args: IMouseEventArgs): void {
    //Customize
  }

  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));