Node Interaction Events in React Diagram Component

21 Oct 202524 minutes to read

The React 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 * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramComponent,
  Node,
  Connector,
} from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
let node = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
    annotations: [
      {
        content: 'Click node',
      },
    ],
  },
];

let connectors = [
  {
    // Unique name for the connector
    id: 'connector1',
    sourceID: 'Start',
    targetPoint: { x: 250, y: 450 },
    type: 'Orthogonal',
    annotations: [
      {
        content: 'Click Connector',
      },
    ],
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      nodes={node}
      connectors={connectors}
      click={(args) => {
        let element = 'Diagram';
        if (args.actualObject instanceof Node) {
          element = 'Node';
        }
        if (args.actualObject instanceof Connector) {
          element = 'Connector';
        }
        alert(element + ' clicked');
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramComponent,
  Node,
  NodeModel,
  Connector,
  ConnectorModel,
  IClickEventArgs
} from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
let node: NodeModel[] = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
    annotations: [
      {
        content: 'Click node',
      },
    ],
  },
];

let connectors: ConnectorModel[] = [
  {
    // Unique name for the connector
    id: 'connector1',
    sourceID: 'Start',
    targetPoint: { x: 250, y: 450 },
    type: 'Orthogonal',
    annotations: [
      {
        content: 'Click Connector',
      },
    ],
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      nodes={node}
      connectors={connectors}
      click={(args: IClickEventArgs) => {
        let element: string = 'Diagram';
        if (args.actualObject instanceof Node) {
          element = 'Node';
        }
        if (args.actualObject instanceof Connector) {
          element = 'Connector';
        }
        alert(element + ' clicked');
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

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 * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramComponent,
} from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
let node = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      nodes={node}
      selectionChange={(args) => {
        if (args.state === 'Changed') {
          console.log('Selection change');
        }
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramComponent,
  NodeModel,
  ISelectionChangeEventArgs
} from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
let node: NodeModel[] = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      nodes={node}
      selectionChange={(args: ISelectionChangeEventArgs) => {
        if (args.state === 'Changed') {
          console.log('Selection change');
        }
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

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

  selectionChange: function (args: ISelectionChangeEventArgs) {
    if (args.state == 'Changing') {
      //Prevents 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 * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent } from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
let node = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      nodes={node}
      positionChange={(args) => {
        if (args.state === 'Completed') {
          console.log('Position change');
        }
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramComponent,
  NodeModel,
  IDraggingEventArgs
} from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
let node: NodeModel[] = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      nodes={node}
      positionChange={(args: IDraggingEventArgs) => {
        if (args.state === 'Completed') {
          console.log('Position change');
        }
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

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

   positionChange: function (args: IDraggingEventArgs) {
    if (args.state == 'Progress') {
      //Prevents 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 * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent } from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
let node = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      nodes={node}
      sizeChange={(args) => {
        if (args.state === 'Completed') {
          console.log('Size change');
        }
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramComponent,
  NodeModel,
  ISizeChangeEventArgs
} from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
let node: NodeModel[] = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      nodes={node}
      sizeChange={(args: ISizeChangeEventArgs) => {
        if (args.state === 'Completed') {
          console.log('Size change');
        }
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

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

    sizeChange: function (args: ISizeChangeEventArgs) {
    if (args.state == 'Progress') {
      //Prevents 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 * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent } from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
let node = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      nodes={node}
      rotateChange={(args) => {
        if (args.state === 'Completed') {
          console.log('Rotate change');
        }
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramComponent,
  NodeModel,
  IRotationEventArgs
} from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
let node: NodeModel[] = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      nodes={node}
      rotateChange={(args: IRotationEventArgs) => {
        if (args.state === 'Completed') {
          console.log('Rotate change');
        }
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

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

  rotateChange: function (args: IRotationEventArgs) {
    if (args.state == 'Progress') {
      //Prevents 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 * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent } from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
let node = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      nodes={node}
      propertyChange={(args) => {
        console.log(args.newValue);
    }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramComponent,
  NodeModel,
  IPropertyChangeEventArgs
} from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
let node: NodeModel[] = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      nodes={node}
      propertyChange={(args: IPropertyChangeEventArgs) => {
        console.log(args.newValue);
    }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

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 * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent } from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
// A node is created and stored in nodes array.
let node = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 150,
    // Size of the node
    width: 100,
    height: 100,
  },
];
var nodes = [
  {
    id: 'node1',
    offsetX: 140,
    offsetY: 250,
    annotations: [{ content: 'node1' }],
  },
  {
    id: 'node2',
    offsetX: 250,
    offsetY: 250,
    annotations: [{ content: 'node2' }],
  },
  {
    id: 'node3',
    offsetX: 360,
    offsetY: 250,
    annotations: [{ content: 'node3' }],
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={'100%'}
      height={'600px'}
      nodes={node}
      collectionChange={(args) => {
        if (args.state === 'Changed') {
          console.log('Collection change');
        }
      }}
      created={() => {
        // Add collection of nodes
        diagramInstance.addElements(nodes);
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, NodeModel, ICollectionChangeEventArgs } from '@syncfusion/ej2-react-diagrams';
let diagramInstance: DiagramComponent;
// A node is created and stored in nodes array.
let node: NodeModel[]= [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 150,
    // Size of the node
    width: 100,
    height: 100,
  },
];
var nodes: NodeModel[] = [
  {
    id: 'node1',
    offsetX: 140,
    offsetY: 250,
    annotations: [{ content: 'node1' }],
  },
  {
    id: 'node2',
    offsetX: 250,
    offsetY: 250,
    annotations: [{ content: 'node2' }],
  },
  {
    id: 'node3',
    offsetX: 360,
    offsetY: 250,
    annotations: [{ content: 'node3' }],
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={'100%'}
      height={'600px'}
      nodes={node}
      collectionChange={(args: ICollectionChangeEventArgs) => {
        if (args.state === 'Changed') {
          console.log('Collection change');
        }
      }}
      created={() => {
        // Add collection of nodes
        diagramInstance.addElements(nodes);
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

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

    collectionChange: function (args: ICollectionChangeEventArgs) {
    if (args.state == 'Changing') {
      //Prevents collection change - Prevents Adding or deleting nodes
      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 * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent } from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
// A node is created and stored in nodes array.
let node = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={'100%'}
      height={'600px'}
      nodes={node}
      mouseEnter={(args) => {
        (args.actualObject).style.fill = 'red';
      }}
      mouseOver={(args) => {
        //Customize
      }}
      mouseLeave={(args) => {
        (args.element).style.fill = 'none';
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, NodeModel, MouseEventArgs } from '@syncfusion/ej2-react-diagrams';
let diagramInstance: DiagramComponent;
// A node is created and stored in nodes array.
let node: NodeModel[] = [
  {
    id: 'Start',
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
  },
];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={'100%'}
      height={'600px'}
      nodes={node}
      mouseEnter={(args: MouseEventArgs) => {
        (args.actualObject as NodeModel).style.fill = 'red';
        diagramInstance.dataBind();
      }}
      mouseOver={(args: MouseEventArgs) => {
        //Customize
      }}
      mouseLeave={(args: MouseEventArgs) => {
        ((args as any).element as NodeModel).style.fill = 'none';
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);