Node Interaction in React Diagram control
29 Jan 202524 minutes to read
The diagram provides support for selecting, dragging, resizing, and rotating nodes interactively. A node can be selected by simply clicking on it, dragged by dragging it on diagram canvas, resized using the resize handle, and rotated using the rotate handle. Additionally, interactions can be performed using some public methods, which are explained below:
Select
You can simply click on the node to select it and click on diagram canvas to unselect it like below.
To select node programatically
A node can be selected at runtime by using the select
method and the selection can be cleared in the diagram by using the clearSelection
or unSelect
method. The following code explains how to select and clear selection in the diagram.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent } from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
let node = [
{
// Position of the node
offsetX: 250,
offsetY: 250,
// Size of the node
width: 100,
height: 100,
// Text(label) added to the node
},
];
// initialize Diagram component
function App() {
const select = () => {
diagramInstance.select([diagramInstance.nodes[0]]);
};
const unSelect = () => {
diagramInstance.clearSelection();
};
return (
<div>
<button onClick={select}>
Select
</button>
<button onClick={unSelect}>
Un Select
</button>
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={node}
/>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, NodeModel } from '@syncfusion/ej2-react-diagrams';
let diagramInstance: DiagramComponent;
let node: NodeModel[] = [
{
// Position of the node
offsetX: 250,
offsetY: 250,
// Size of the node
width: 100,
height: 100,
// Text(label) added to the node
},
];
// initialize Diagram component
function App() {
const select = () => {
diagramInstance.select([diagramInstance.nodes[0]]);
};
const unSelect = () => {
diagramInstance.clearSelection();
};
return (
<div>
<button onClick={select}>
Select
</button>
<button onClick={unSelect}>
Un Select
</button>
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={node}
/>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
Method | Parameter | Description |
---|---|---|
unSelect |
NodeModel/ConnectorModel | The object to remove from the selection. |
clearSelection |
- | Clears all the selection in the diagram. |
Drag
You can simply mousedown on a node and drag it anywhere on the diagram canvas like below.
To drag node programatically
A node can be dragged at runtime by using the drag
method. The following code explains how to drag the node by using the drag method.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent } from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
let node = [
{
// Position of the node
offsetX: 250,
offsetY: 250,
// Size of the node
width: 100,
height: 100,
// Text(label) added to the node
},
];
// initialize Diagram component
function App() {
const drag = () => {
diagramInstance.drag(diagramInstance.nodes[0], 20, 20);
};
return (
<div>
<button onClick={drag}>Drag</button>
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={node}
/>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, NodeModel } from '@syncfusion/ej2-react-diagrams';
let diagramInstance: DiagramComponent;
let node: NodeModel[] = [
{
// Position of the node
offsetX: 250,
offsetY: 250,
// Size of the node
width: 100,
height: 100,
// Text(label) added to the node
},
];
// initialize Diagram component
function App() {
const drag = () => {
diagramInstance.drag(diagramInstance.nodes[0], 20, 20);
};
return (
<div>
<button onClick={drag}>
Drag
</button>
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={node}
/>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
Resize
When we select a node a resize handle will appear on all the sides of the node. We can resize the node by clicking and dragging the resize handle.
To resize node programatically
A node can be resized at runtime by using the scale
method. The following code explains how to resize the node by using the scale method.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent } from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
let node = [
{
// Position of the node
offsetX: 250,
offsetY: 250,
// Size of the node
width: 100,
height: 100,
// Text(label) added to the node
},
];
// initialize Diagram component
function App() {
const reSize = () => {
diagramInstance.scale(diagramInstance.nodes[0], 0.5, 0.5, { x: 0.5, y: 0.5 });
};
return (
<div>
<button onClick={reSize}>Resize</button>
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={node}
/>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, NodeModel } from '@syncfusion/ej2-react-diagrams';
let diagramInstance: DiagramComponent;
let node: NodeModel[] = [
{
// Position of the node
offsetX: 250,
offsetY: 250,
// Size of the node
width: 100,
height: 100,
// Text(label) added to the node
},
];
// initialize Diagram component
function App() {
const reSize = () => {
diagramInstance.scale(diagramInstance.nodes[0], 0.5, 0.5, { x: 0.5, y: 0.5 });
};
return (
<div>
<button onClick={reSize}>Resize</button>
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={node}
/>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
Rotate
A node can be rotated interactively by clicking and dragging the rotate handle of the node.
To rotate node programatically
A node can be rotated at runtime by using the rotate
method. The following code explains how to rotate the node by using the rotate method.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent } from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
let node = [
{
// Position of the node
offsetX: 250,
offsetY: 250,
// Size of the node
width: 100,
height: 100,
// Text(label) added to the node
},
];
// initialize Diagram component
function App() {
const rotate = () => {
diagramInstance.rotate(diagramInstance.nodes[0], diagramInstance.nodes[0].rotateAngle + 15);
};
return (
<div>
<button onClick={rotate}>Rotate</button>
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={node}
/>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, NodeModel } from '@syncfusion/ej2-react-diagrams';
let diagramInstance: DiagramComponent;
let node: NodeModel[] = [
{
// Position of the node
offsetX: 250,
offsetY: 250,
// Size of the node
width: 100,
height: 100,
// Text(label) added to the node
},
];
// initialize Diagram component
function App() {
const rotate = () => {
diagramInstance.rotate(diagramInstance.nodes[0], diagramInstance.nodes[0].rotateAngle + 15);
};
return (
<div>
<button onClick={rotate}>Rotate</button>
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={node}
/>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
Flip
The diagram Provides support to flip the node. flip
is performed to
give the mirrored image of the original element.
The flip types are as follows:
-
HorizontalFlip
Horizontal
is used to change the element in horizontal direction. -
VerticalFlip
Vertical
is used to change the element in vertical direction -
Both
Both
which involves both vertical and horizontal changes of the element.
The following code illustrates how to provide the mirror image of the original element.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { DiagramComponent, FlipDirection } from "@syncfusion/ej2-react-diagrams";
// A node is created and stored in nodes array.
let node = [{
// Position of the node
offsetX: 250,
offsetY: 250,
// Size of the node
width: 100,
height: 100,
// Flip the node in Horizontal Direction
flip: FlipDirection.Horizontal,
shape: {
type: 'Basic',
shape: 'RightTriangle',
},
style: {
fill: '#6BA5D7',
strokeColor: 'white'
}
// Text(label) added to the node
}];
let diagramInstance;
function App() {
return (<DiagramComponent id="container" ref={(diagram) => (diagramInstance = diagram)} width={'100%'} height={'600px'} nodes={node} created={() => {
diagramInstance.select([diagramInstance.nodes[0]]);
}}/>);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
Diagram,
DiagramComponent,
NodeModel,
BasicShapeModel,
FlipDirection
} from "@syncfusion/ej2-react-diagrams";
// A node is created and stored in nodes array.
let node: NodeModel[] = [{
// Position of the node
offsetX: 250,
offsetY: 250,
// Size of the node
width: 100,
height: 100,
// Flip the node in Horizontal Direction
flip: FlipDirection.Horizontal,
shape: {
type: 'Basic',
shape: 'RightTriangle',
},
style: {
fill: '#6BA5D7',
strokeColor: 'white'
}
// Text(label) added to the node
}];
let diagramInstance: DiagramComponent;
function App() {
return (
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={node}
created={() => {
diagramInstance.select([diagramInstance.nodes[0]]);
}}
// render initialized Diagram
/>
);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
Note: The flip is also applicable for group and BPMN shapes.
Update flip at runtime
You can dynamically update the flip for a node at runtime using the ^
operator. This operator allows you to apply the same flip direction multiple times, toggling the node’s orientation effectively.
The following example demonstrates how to update the flip for a node dynamically:
import * as React from "react";
import * as ReactDOM from "react-dom";
import { DiagramComponent, FlipDirection } from "@syncfusion/ej2-react-diagrams";
// A node is created and stored in nodes array.
let node = [{
// Position of the node
offsetX: 250,
offsetY: 250,
// Size of the node
width: 100,
height: 100,
// Flip the node in Horizontal Direction
flip: FlipDirection.Horizontal,
shape: {
type: 'Basic',
shape: 'RightTriangle',
},
style: {
fill: '#6BA5D7',
strokeColor: 'white'
}
// Text(label) added to the node
}];
let diagramInstance;
function App() {
const flipHorizontal = () => {
diagramInstance.nodes[0].flip ^= FlipDirection.Horizontal;
diagramInstance.dataBind();
};
const flipVertical = () => {
diagramInstance.nodes[0].flip ^= FlipDirection.Vertical;
diagramInstance.dataBind();
};
const flipBoth = () => {
diagramInstance.nodes[0].flip ^= FlipDirection.Both;
diagramInstance.dataBind();
};
const flipNone = () => {
diagramInstance.nodes[0].flip = FlipDirection.None;
diagramInstance.dataBind();
};
return (
<div>
<button onClick={flipHorizontal}>flipHorizontal</button>
<button onClick={flipVertical}>flipVertical</button>
<button onClick={flipBoth}>flipBoth</button>
<button onClick={flipNone}>flipNone</button>
<DiagramComponent id="container" ref={(diagram) => (diagramInstance = diagram)} width={'100%'} height={'600px'} nodes={node} />
</div>);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
Diagram,
DiagramComponent,
NodeModel,
BasicShapeModel,
FlipDirection
} from "@syncfusion/ej2-react-diagrams";
// A node is created and stored in nodes array.
let node: NodeModel[] = [{
// Position of the node
offsetX: 250,
offsetY: 250,
// Size of the node
width: 100,
height: 100,
// Flip the node in Horizontal Direction
flip:FlipDirection.Horizontal,
shape: {
type: 'Basic',
shape: 'RightTriangle',
},
style: {
fill: '#6BA5D7',
strokeColor: 'white'
}
// Text(label) added to the node
}];
let diagramInstance: DiagramComponent;
function App() {
const flipHorizontal = () => {
diagramInstance.nodes[0].flip ^= FlipDirection.Horizontal;
diagramInstance.dataBind();
};
const flipVertical = () => {
diagramInstance.nodes[0].flip ^= FlipDirection.Vertical;
diagramInstance.dataBind();
};
const flipBoth = () => {
diagramInstance.nodes[0].flip ^= FlipDirection.Both;
diagramInstance.dataBind();
};
const flipNone = () => {
diagramInstance.nodes[0].flip = FlipDirection.None;
diagramInstance.dataBind();
};
return (
<div>
<button onClick={flipHorizontal}>flipHorizontal</button>
<button onClick={flipVertical}>flipVertical</button>
<button onClick={flipBoth}>flipBoth</button>
<button onClick={flipNone}>flipNone</button>
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={node}
// render initialized Diagram
/>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
Flip modes
The flipMode
is used to control the behavior of the flip object whether to flip the object along with the port and label.
FlipMode | Description |
---|---|
Label | It flips the label along with the object while keeping the text readable. |
Port | It flips the port along with the object. |
All | It flips the port, label, and label text along with the object. |
None | It flips only the object. |
LabelText | It flips the object and inverts the label without changing its position. |
PortAndLabel | It flips the port and label along with the object while keeping the text readable. |
PortAndLabelText | It flips the port and label text along with the object. |
LabelAndLabelText | It flips the label and label text along with the Object. |
Below are examples of a node undergoing various FlipModes in different flip directions.
Flip Direction | Flip Mode | Default Node | Flipped Node |
---|---|---|---|
Horizontal | All | ![]() |
![]() |
Horizontal | Label | ![]() |
![]() |
Horizontal | LabelText | ![]() |
![]() |
Horizontal | Port | ![]() |
![]() |
Horizontal | None | ![]() |
![]() |
Horizontal | PortAndLabel | ![]() |
![]() |
Horizontal | PortAndLabelText | ![]() |
![]() |
Horizontal | LabelAndLabelText | ![]() |
![]() |
Vertical | All | ![]() |
![]() |
Vertical | Label | ![]() |
![]() |
Vertical | LabelText | ![]() |
![]() |
Vertical | Port | ![]() |
![]() |
Vertical | None | ![]() |
![]() |
Vertical | PortAndLabel | ![]() |
![]() |
Vertical | PortAndLabelText | ![]() |
![]() |
Vertical | LabelAndLabelText | ![]() |
![]() |
Both | All | ![]() |
![]() |
Both | Label | ![]() |
![]() |
Both | LabelText | ![]() |
![]() |
Both | Port | ![]() |
![]() |
Both | None | ![]() |
![]() |
Both | PortAndLabel | ![]() |
![]() |
Both | PortAndLabelText | ![]() |
![]() |
Both | LabelAndLabelText | ![]() |
![]() |
import * as React from 'react';
import { createRoot } from 'react-dom/client';
import {
DiagramComponent,
PortVisibility,
FlipDirection,
} from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
var nodes = [
{
id: 'node1',
// Position of the node
offsetX: 100,
offsetY: 100,
// Size of the node
width: 100,
height: 100,
ports: [
{
id: 'left',
offset: { x: 0, y: 0.5 },
visibility: PortVisibility.Visible,
},
],
annotations: [{ content: 'FlipMode as Label', offset: { x: 0, y: 0.8 } }],
// Flip the node in Horizontal Direction
flip: FlipDirection.Horizontal,
//FlipMode as Label
flipMode: 'Label',
shape: {
type: 'Basic',
shape: 'RightTriangle',
},
style: {
fill: '#6BA5D7',
},
},
{
id: 'node2',
// Position of the node
offsetX: 400,
offsetY: 100,
// Size of the node
width: 100,
height: 100,
annotations: [{ content: 'FlipMode as Port', offset: { x: 0, y: 0.8 } }],
// Flip the node in Horizontal Direction
flip: FlipDirection.Horizontal,
ports: [
{
id: 'left',
offset: { x: 0, y: 0.5 },
visibility: PortVisibility.Visible,
},
],
//FlipMode as Port
flipMode: 'Port',
shape: {
type: 'Basic',
shape: 'RightTriangle',
},
style: {
fill: '#6BA5D7',
},
},
{
id: 'node3',
// Position of the node
offsetX: 100,
offsetY: 300,
// Size of the node
width: 100,
height: 100,
annotations: [{ content: 'FlipMode as All', offset: { x: 0, y: 0.8 } }],
// Flip the node in Horizontal Direction
flip: FlipDirection.Horizontal,
ports: [
{
id: 'left',
offset: { x: 0, y: 0.5 },
visibility: PortVisibility.Visible,
},
],
//FlipMode as All
flipMode: 'All',
shape: {
type: 'Basic',
shape: 'RightTriangle',
},
style: {
fill: '#6BA5D7',
},
},
{
id: 'node4',
// Position of the node
offsetX: 400,
offsetY: 300,
// Size of the node
width: 100,
height: 100,
annotations: [{ content: 'FlipMode as None', offset: { x: 0, y: 0.8 } }],
// Flip the node in Horizontal Direction
flip: FlipDirection.Horizontal,
ports: [
{
id: 'left',
offset: { x: 0, y: 0.5 },
visibility: PortVisibility.Visible,
},
],
//FlipMode as None
flipMode: 'None',
shape: {
type: 'Basic',
shape: 'RightTriangle',
},
style: {
fill: '#6BA5D7',
},
},
];
let diagramInstance;
function App() {
return (
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={nodes}
created={() => {
diagramInstance.select([diagramInstance.nodes[0]]);
}}
/>
);
}
export default App;
const root = createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import { createRoot } from 'react-dom/client';
import {
DiagramComponent,
PortVisibility,
FlipDirection,
NodeModel
} from '@syncfusion/ej2-react-diagrams';
// A node is created and stored in nodes array.
var nodes : NodeModel[] = [
{
id: 'node1',
// Position of the node
offsetX: 100,
offsetY: 100,
// Size of the node
width: 100,
height: 100,
ports: [
{
id: 'left',
offset: { x: 0, y: 0.5 },
visibility: PortVisibility.Visible,
},
],
annotations: [{ content: 'FlipMode as Label', offset: { x: 0, y: 0.8 } }],
// Flip the node in Horizontal Direction
flip: FlipDirection.Horizontal,
//FlipMode as Label
flipMode: 'Label',
shape: {
type: 'Basic',
shape: 'RightTriangle',
},
style: {
fill: '#6BA5D7',
},
},
{
id: 'node2',
// Position of the node
offsetX: 400,
offsetY: 100,
// Size of the node
width: 100,
height: 100,
annotations: [{ content: 'FlipMode as Port', offset: { x: 0, y: 0.8 } }],
// Flip the node in Horizontal Direction
flip: FlipDirection.Horizontal,
ports: [
{
id: 'left',
offset: { x: 0, y: 0.5 },
visibility: PortVisibility.Visible,
},
],
//FlipMode as Port
flipMode: 'Port',
shape: {
type: 'Basic',
shape: 'RightTriangle',
},
style: {
fill: '#6BA5D7',
},
},
{
id: 'node3',
// Position of the node
offsetX: 100,
offsetY: 300,
// Size of the node
width: 100,
height: 100,
annotations: [{ content: 'FlipMode as All', offset: { x: 0, y: 0.8 } }],
// Flip the node in Horizontal Direction
flip: FlipDirection.Horizontal,
ports: [
{
id: 'left',
offset: { x: 0, y: 0.5 },
visibility: PortVisibility.Visible,
},
],
//FlipMode as All
flipMode: 'All',
shape: {
type: 'Basic',
shape: 'RightTriangle',
},
style: {
fill: '#6BA5D7',
},
},
{
id: 'node4',
// Position of the node
offsetX: 400,
offsetY: 300,
// Size of the node
width: 100,
height: 100,
annotations: [{ content: 'FlipMode as None', offset: { x: 0, y: 0.8 } }],
// Flip the node in Horizontal Direction
flip: FlipDirection.Horizontal,
ports: [
{
id: 'left',
offset: { x: 0, y: 0.5 },
visibility: PortVisibility.Visible,
},
],
//FlipMode as None
flipMode: 'None',
shape: {
type: 'Basic',
shape: 'RightTriangle',
},
style: {
fill: '#6BA5D7',
},
},
];
let diagramInstance: DiagramComponent;
function App() {
return (
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={nodes}
created={() => {
diagramInstance.select([diagramInstance.nodes[0]]);
}}
/>
);
}
export default App;
const root = createRoot(document.getElementById('diagram'));
root.render(<App />);