Nodes in React Diagram Component

21 Oct 202524 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 * 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 = [{
        // Position of the node
        offsetX: 250,
        offsetY: 250,
        // Size of the node
        width: 100,
        height: 100,
        style: {
            fill: '#6BA5D7',
            strokeColor: 'white'
        },
        // Text(label) added to the node
    }];
// initialize Diagram component
function App() {
    return (<DiagramComponent id="container" width={'100%'} height={'600px'} 
    // Add node
    nodes={node}/>);
}
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
} 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,
    style: {
        fill: '#6BA5D7',
        strokeColor: 'white'
    },
    // Text(label) added to the node
}];
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      // Add node
      nodes={node}
      // render initialized Diagram
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

NOTE

Node id should not begin with numbers(should begin with a letter). Node Id should be unique for all the shapes and connectors.

Create Node 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 * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramComponent,
  Inject,
  DataBinding,
} from '@syncfusion/ej2-react-diagrams';
import { DataManager, Query } from '@syncfusion/ej2-data';
let diagramInstance;
let data = [
  {
    id: 'data1',
    parent: null,
  },
];
let items = new DataManager(data, new Query().take(7));
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={'100%'}
      height={'700px'}
      getNodeDefaults={(node) => {
        node.height = 100;
        node.width = 100;
        node.offsetX = 300;
        node.offsetY = 200;
        node.style = { fill: 'yellow', strokeColor: 'yellow' };
        return node;
      }}
      dataSourceSettings=
    >
      <Inject services={[DataBinding]} />
    </DiagramComponent>
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramComponent,
  Inject,
  DataBinding,
} from '@syncfusion/ej2-react-diagrams';
import { DataManager, Query } from '@syncfusion/ej2-data';
let diagramInstance: DiagramComponent;
let data: any = [
  {
    id: 'data1',
    parent: null,
  },
];
let items: any = new DataManager(data, new Query().take(7));
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={'100%'}
      height={'700px'}
      getNodeDefaults={(node) => {
        node.height = 100;
        node.width = 100;
        node.offsetX = 300;
        node.offsetY = 200;
        node.style = { fill: 'yellow', strokeColor: 'yellow' };
        return node;
      }}
      dataSourceSettings=
    >
      <Inject services={[DataBinding]} />
    </DiagramComponent>
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

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 * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, SymbolPalette,
    SymbolPaletteComponent, } 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,
  },
];
export function getBasicShapes() {
    let basicShapes = [
        {
            id: "Rectangle",
            shape: {
                type: "Basic",
                shape: "Rectangle",
            },
            height: 100,
            width: 100
        },
    ];
    return basicShapes;
}
// initialize Diagram component
function App() {
  return (
    <div  style={{width:'100%'}}>
        <div style={{float: 'left', width:'30%'}}>
         <SymbolPaletteComponent id="palette" width={'100%'} height={"700px"}
         palettes={[
            {
                id: 'basic',
                title: 'Basic Shapes',
                symbols: getBasicShapes(),
            },
        ]} 
    //Specifies the size of the symbol
    symbolHeight={80} symbolWidth={80} 
    //Sets the space to be left around a symbol
    symbolMargin={{
            left: 15,
            right: 15,
            top: 0,
            bottom: 15,
        }} />
         </div>
         <div style={{float: 'right', width:'70%'}}>
      <DiagramComponent
        id="container"
        ref={(diagram) => (diagramInstance = diagram)}
        width={'70%'}
        height={'700px'}
        nodes={node}
      />
      </div>
    </div>
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent,
    SymbolPaletteComponent, 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,
  },
];
export function getBasicShapes() {
    let basicShapes = [
        {
            id: "Rectangle",
            shape: {
                type: "Basic",
                shape: "Rectangle",
            },
            height: 100,
            width: 100
        },
    ];
    return basicShapes;
}
// initialize Diagram component
function App() {
  return (
    <div  style={{width:'100%'}}>
        <div style={{float: 'left', width:'30%'}}>
         <SymbolPaletteComponent id="palette" width={'100%'} height={"700px"}
         palettes={[
            {
                id: 'basic',
                title: 'Basic Shapes',
                symbols: getBasicShapes(),
            },
        ]} 
    //Specifies the size of the symbol
    symbolHeight={80} symbolWidth={80} 
    //Sets the space to be left around a symbol
    symbolMargin={{
            left: 15,
            right: 15,
            top: 0,
            bottom: 15,
        }} />
         </div>
         <div style={{float: 'right', width:'70%'}}>
      <DiagramComponent
        id="container"
        ref={(diagram) => (diagramInstance = diagram)}
        width={'70%'}
        height={'700px'}
        nodes={node}
      />
      </div>
    </div>
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

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.

The following code example illustrates how to draw a rectangle at runtime.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, DiagramTools } from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
// initialize Diagram component
function App() {
  return (
      <DiagramComponent
        id="container"
        ref={(diagram) => (diagramInstance = diagram)}
        width={'100%'}
        height={'700px'}
        created={() => {
            //JSON to create a rectangle
            let drawingshape = {
              type: 'Basic',
              shape: 'Rectangle',
            };
            let node = {
              shape: drawingshape,
            };
            diagramInstance.drawingObject = node;
            //To draw an object once, activate draw once
            diagramInstance.tool = DiagramTools.ContinuousDraw;
            diagramInstance.dataBind();
          }}
      />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, DiagramTools } from '@syncfusion/ej2-react-diagrams';
let diagramInstance: DiagramComponent;
// initialize Diagram component
function App() {
  return (
      <DiagramComponent
        id="container"
        ref={(diagram) => (diagramInstance = diagram)}
        width={'100%'}
        height={'700px'}
        created={() => {
            //JSON to create a rectangle
            let drawingshape = {
              type: 'Basic',
              shape: 'Rectangle',
            };
            let node = {
              shape: drawingshape,
            };
            diagramInstance.drawingObject = node;
            //To draw an object once, activate draw once
            diagramInstance.tool = DiagramTools.ContinuousDraw;
            diagramInstance.dataBind();
          }}
      />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

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.

The following code illustrates how to add a node.

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,
  },
];
// initialize Diagram component
function App() {
  const add = () => {
    diagramInstance.add(node[0]);
  };
  const remove = () => {
    diagramInstance.remove(diagramInstance.nodes[0]);
  };
  return (
    <div>
      <button onClick={add}>Add Node</button>
      <button onClick={remove}>Remove Node</button>
      <DiagramComponent
        id="container"
        ref={(diagram) => (diagramInstance = diagram)}
        width={'100%'}
        height={'600px'}
      />
    </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,
  },
];
// initialize Diagram component
function App() {
  const add = () => {
    diagramInstance.add(node[0]);
  };
  const remove = () => {
    diagramInstance.remove(diagramInstance.nodes[0]);
  };
  return (
    <div>
      <button onClick={add}>Add Node</button>
      <button onClick={remove}>Remove Node</button>
      <DiagramComponent
        id="container"
        ref={(diagram) => (diagramInstance = diagram)}
        width={'100%'}
        height={'600px'}
      />
    </div>
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

Add Multiple Nodes Simultaneously

Collections of nodes can be efficiently added using theaddElements method. This approach is optimal for bulk operations and triggers the collectionChange event for each added element.

The following code illustrates how to add nodes collection at run time.

import * as React from "react";
import * as ReactDOM from "react-dom";
import {DiagramComponent }from "@syncfusion/ej2-react-diagrams";
let diagramInstance;
// initialize nodes collection
var node = [
    { 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={'1500px'} height={'600px'}
    getNodeDefaults={(node) => {
        node.height = 100;
        node.width = 100;
        node.style.fill = '#6BA5D7';
        node.style.strokeColor = 'white';
        return node;
      }}
    created={() => {
            // Add collection of nodes 
            diagramInstance.addElements(node);
        }}/>);
}
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} from "@syncfusion/ej2-react-diagrams";

let diagramInstance:DiagramComponent;
//initialize node collection
var node:NodeModel= [
    { id: 'node1', offsetX: 35, offsetY: 260 ,annotations: [{ content: 'node1' }]},
    { id: 'node2', offsetX: 140, offsetY: 260 ,annotations: [{ content: 'node2' }]},
    { id: 'node3', offsetX: 240, offsetY: 260 ,annotations: [{ content: 'node3' }]}
];// initialize Diagram component
function App() {
    return (
      <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={'1500px'}
      height={'600px'}
      getNodeDefaults={(node: NodeModel) => {
        node.height = 100;
        node.width = 100;
        node.style.fill = '#6BA5D7';
        node.style.strokeColor = 'white';
        return node;
      }}
        created={() => {
            // Add collection of nodes 
            diagramInstance.addElements(node);
        }}
      />
    );
  }
  const root = ReactDOM.createRoot(document.getElementById('diagram'));
  root.render(<App />);

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 * 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,
    style: { fill: '#6AA8D7',strokeWidth:1},
  },
];
// initialize Diagram component
function App() {
  const color = () => {
      if(diagramInstance.nodes[0].style.fill === '#6AA8D7'){
        diagramInstance.nodes[0].style.fill = 'orange';
      }
      else{
        diagramInstance.nodes[0].style.fill = '#6AA8D7';
      }
  };
  const size = () => {
    if(diagramInstance.nodes[0].width === 100){
        diagramInstance.nodes[0].width = 200;
      }
      else{
        diagramInstance.nodes[0].width =100;
      }
  };
  return (
    <div>
      <button onClick={color}>Change Color</button>
      <button onClick={size}>Change Size</button>
      <DiagramComponent
        id="container"
        ref={(diagram) => (diagramInstance = diagram)}
        nodes={node}
        width={'100%'}
        height={'600px'}
      />
    </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,
    style: { fill: '#6AA8D7',strokeWidth:1},
  },
];
// initialize Diagram component
function App() {
  const color = () => {
      if(diagramInstance.nodes[0].style.fill === '#6AA8D7'){
        diagramInstance.nodes[0].style.fill = 'orange';
      }
      else{
        diagramInstance.nodes[0].style.fill = '#6AA8D7';
      }
  };
  const size = () => {
    if(diagramInstance.nodes[0].width === 100){
        diagramInstance.nodes[0].width = 200;
      }
      else{
        diagramInstance.nodes[0].width =100;
      }
  };
  return (
    <div>
      <button onClick={color}>Change Color</button>
      <button onClick={size}>Change Size</button>
      <DiagramComponent
        id="container"
        ref={(diagram) => (diagramInstance = diagram)}
        nodes={node}
        width={'100%'}
        height={'600px'}
      />
    </div>
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

NOTE

Call the dataBind dataBind method after property updates to ensure immediate reflection of changes.

Clone Node at Runtime

Node cloning creates new instances with identical properties and attributes. Use the copy and paste methods to duplicate existing nodes programmatically.

The following code example illustrates how to clone node at runtime

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,
    style: { fill: '#6AA8D7', strokeWidth: 1 },
  },
];
// initialize Diagram component
function App() {
  const clone = () => {
    let selectedNode =
      diagramInstance.selectedItems.nodes.length > 0
        ? diagramInstance.selectedItems.nodes[0]
        : diagramInstance.nodes[0];
    diagramInstance.select([selectedNode]);
    diagramInstance.copy();
    diagramInstance.paste();
  };
  return (
    <div>
      <button onClick={clone}>Clone Node</button>
      <DiagramComponent
        id="container"
        ref={(diagram) => (diagramInstance = diagram)}
        nodes={node}
        width={'100%'}
        height={'600px'}
      />
    </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,
    style: { fill: '#6AA8D7',strokeWidth:1},
  },
];
// initialize Diagram component
function App() {
  const clone = () => {
    let selectedNode =
      diagramInstance.selectedItems.nodes.length > 0
        ? diagramInstance.selectedItems.nodes[0]
        : diagramInstance.nodes[0];
    diagramInstance.select([selectedNode]);
    diagramInstance.copy();
    diagramInstance.paste();
  };
  return (
    <div>
      <button onClick={clone}>Clone Node</button>
      <DiagramComponent
        id="container"
        ref={(diagram) => (diagramInstance = diagram)}
        nodes={node}
        width={'100%'}
        height={'600px'}
      />
    </div>
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

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