Layout events in React Diagram Component
21 Oct 202524 minutes to read
Layout events in the React Diagram component provide developers with hooks to respond to various stages of automatic layout processing. These events are particularly useful when working with hierarchical data structures and need to customize behavior during layout rendering, data loading, or node expansion/collapse operations.
The diagram component supports several layout-specific events that fire during different phases of the layout life cycle, enabling fine-grained control over layout behavior and user interactions.
DataLoaded Event
The dataLoaded event triggers after the diagram successfully populates from an external data source. This event provides access to the loaded data and diagram instance, making it ideal for performing post-load customizations such as applying custom styling, setting initial node states, or configuring layout-specific properties.
The event fires once the data binding process completes but before the initial layout calculation begins, providing an opportunity to modify nodes or connectors before they are positioned.
The following code example explains the data loaded event in the diagram.
function dataLoaded(args) {
//we can get diagram instance in args.
console.log(args);
}
<DiagramComponent id="diagram" width={'100%'} height={'600px'}
nodes={nodes} connectors={connectors}
// Event Triggers when the state of the layout rendering changes
dataLoaded={dataLoaded}
//Uses layout to auto-arrange nodes on the diagram page
layout=>
{/* Inject necessary services for the diagram */}
<Inject services={[HierarchicalTree]} />
</DiagramComponent>ExpandStateChange Event
The expandStateChange event fires when a user clicks the expand or collapse icon of a node in a hierarchical layout. This event occurs before the layout update begins, allowing developers to prevent the state change, modify the expansion behavior, or trigger custom actions based on the node’s new state.
The event provides information about the affected node, its current state, and whether the operation can be canceled. This makes it valuable for implementing conditional expansion, loading child data on-demand, or applying custom animations.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, HierarchicalTree } from '@syncfusion/ej2-react-diagrams';
//Initialize nodes
let nodes = [
{
id: 'Start',
width: 140,
height: 50,
offsetX: 300,
offsetY: 50,
annotations: [{ content: 'Node1' }],
style: { fill: '#6BA5D7', strokeColor: 'white' },
expandIcon: {
shape: 'ArrowDown',
width: 20,
height: 15,
},
collapseIcon: {
shape: 'ArrowUp',
width: 20,
height: 15,
},
},
{
id: 'Init',
width: 140,
height: 50,
offsetX: 300,
offsetY: 140,
style: { fill: '#6BA5D7', strokeColor: 'white' },
annotations: [{ content: 'Node2' }],
},
];
//Initializes connectors
let connectors = [{
id: 'connector1',
sourceID: 'Start',
targetID: 'Init',
type: 'Orthogonal',
}];
export default function App() {
// Function expand/collapse state changes
function expandStateChange(args) {
//We can get the expanded or collapsed state in args
console.log('Expanded ' + args.state);
}
return (
<div>
<DiagramComponent
id="container"
width={'100%'}
height={'550px'}
nodes={nodes}
connectors={connectors}
// Event Triggers when the state of the expand and collapse icon change
expandStateChange={expandStateChange}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//Sets layout type
type: 'HierarchicalTree',
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[HierarchicalTree]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, HierarchicalTree, ConnectorModel, NodeModel, IExpandStateChangeEventArgs } from '@syncfusion/ej2-react-diagrams';
//Initialize nodes
let nodes: NodeModel[] = [
{
id: 'Start',
width: 140,
height: 50,
offsetX: 300,
offsetY: 50,
annotations: [{ content: 'Node1' }],
style: { fill: '#6BA5D7', strokeColor: 'white' },
expandIcon: {
shape: 'ArrowDown',
width: 20,
height: 15,
},
collapseIcon: {
shape: 'ArrowUp',
width: 20,
height: 15,
},
},
{
id: 'Init',
width: 140,
height: 50,
offsetX: 300,
offsetY: 140,
style: { fill: '#6BA5D7', strokeColor: 'white' },
annotations: [{ content: 'Node2' }],
},
];
//Initializes connectors
let connectors: ConnectorModel[] = [{
id: 'connector1',
sourceID: 'Start',
targetID: 'Init',
type: 'Orthogonal',
}];
export default function App() {
// Function expand/collapse state changes
function expandStateChange(args: IExpandStateChangeEventArgs) {
//We can get the expanded or collapsed state in args
console.log('Expanded ' + args.state);
}
return (
<div>
<DiagramComponent
id="container"
width={'100%'}
height={'550px'}
nodes={nodes}
connectors={connectors}
// Event Triggers when the state of the expand and collapse icon change
expandStateChange={expandStateChange}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//Sets layout type
type: 'HierarchicalTree',
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[HierarchicalTree]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById('diagram') as HTMLElement);
root.render(<App />);Animation Complete Event
The animationComplete event triggers after the diagram finishes animating layout changes, particularly during expand and collapse operations. This event is essential for detecting when visual transitions have completed, enabling developers to perform follow-up actions such as scrolling to specific nodes, updating UI indicators, or triggering additional layout adjustments.
The event fires at the end of the animation cycle, ensuring that all visual updates are complete before any subsequent operations begin.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, HierarchicalTree, LayoutAnimation } from '@syncfusion/ej2-react-diagrams';
//Initialize nodes
let nodes = [
{
id: 'Start',
width: 140,
height: 50,
offsetX: 300,
offsetY: 50,
annotations: [{ content: 'Node1' }],
style: { fill: '#6BA5D7', strokeColor: 'white' },
expandIcon: {
shape: 'ArrowDown',
width: 20,
height: 15,
},
collapseIcon: {
shape: 'ArrowUp',
width: 20,
height: 15,
},
},
{
id: 'Init',
width: 140,
height: 50,
offsetX: 300,
offsetY: 140,
style: { fill: '#6BA5D7', strokeColor: 'white' },
annotations: [{ content: 'Node2' }],
},
{
id: 'Init2',
width: 140,
height: 50,
offsetX: 100,
offsetY: 140,
style: { fill: '#6BA5D7', strokeColor: 'white' },
annotations: [{ content: 'Node3' }],
},
{
id: 'Init3',
width: 140,
height: 50,
offsetX: 150,
offsetY: 140,
style: { fill: '#6BA5D7', strokeColor: 'white' },
annotations: [{ content: 'Node4' }],
}
];
//Initializes connectors
let connectors = [
{
id: 'connector1',
sourceID: 'Start',
targetID: 'Init',
type: 'Orthogonal',
},
{
id: 'connector2',
sourceID: 'Start',
targetID: 'Init2',
type: 'Orthogonal',
},
{
id: 'connector3',
sourceID: 'Init2',
targetID: 'Init3',
type: 'Orthogonal',
}
];
export default function App() {
let diagramInstance;
// Function to handle animation state changes
function animationComplete() {
console.log('Animation complete');
diagramInstance.nodes[0].style.fill =
diagramInstance.nodes[0].style.fill === '#6BA5D7' ? 'red' : '#6BA5D7';
diagramInstance.dataBind();
//customize
}
return (
<div>
<DiagramComponent
id="container"
width={'80%'}
height={'550px'}
nodes={nodes}
connectors={connectors}
ref={(diagram) => (diagramInstance = diagram)}
// Event Triggers when animation complete
animationComplete={animationComplete}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//Sets layout type
type: 'HierarchicalTree',
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[LayoutAnimation, HierarchicalTree]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, HierarchicalTree, LayoutAnimation, ConnectorModel, NodeModel, ShapeStyleModel } from '@syncfusion/ej2-react-diagrams';
//Initialize nodes
let nodes: NodeModel[] = [
{
id: 'Start',
width: 140,
height: 50,
offsetX: 300,
offsetY: 50,
annotations: [{ content: 'Node1' }],
style: { fill: '#6BA5D7', strokeColor: 'white' },
expandIcon: {
shape: 'ArrowDown',
width: 20,
height: 15,
},
collapseIcon: {
shape: 'ArrowUp',
width: 20,
height: 15,
},
},
{
id: 'Init',
width: 140,
height: 50,
offsetX: 300,
offsetY: 140,
style: { fill: '#6BA5D7', strokeColor: 'white' },
annotations: [{ content: 'Node2' }],
},
{
id: 'Init2',
width: 140,
height: 50,
offsetX: 100,
offsetY: 140,
style: { fill: '#6BA5D7', strokeColor: 'white' },
annotations: [{ content: 'Node3' }],
},
{
id: 'Init3',
width: 140,
height: 50,
offsetX: 150,
offsetY: 140,
style: { fill: '#6BA5D7', strokeColor: 'white' },
annotations: [{ content: 'Node4' }],
}
];
//Initializes connectors
let connectors: ConnectorModel[] = [
{
id: 'connector1',
sourceID: 'Start',
targetID: 'Init',
type: 'Orthogonal',
},
{
id: 'connector2',
sourceID: 'Start',
targetID: 'Init2',
type: 'Orthogonal',
},
{
id: 'connector3',
sourceID: 'Init2',
targetID: 'Init3',
type: 'Orthogonal',
}
];
export default function App() {
let diagramInstance: DiagramComponent;
// Function to handle animation state changes
function animationComplete() {
console.log('Animation complete');
(diagramInstance.nodes[0].style as ShapeStyleModel).fill =
(diagramInstance.nodes[0].style as ShapeStyleModel).fill === '#6BA5D7' ? 'red' : '#6BA5D7';
diagramInstance.dataBind();
//customize
}
return (
<div>
<DiagramComponent
id="container"
width={'80%'}
height={'550px'}
nodes={nodes}
connectors={connectors}
ref={(diagram: any) => (diagramInstance = diagram)}
// Event Triggers when the animation complete
animationComplete={animationComplete}
//Uses layout to auto-arrange nodes on the diagram page
layout={{
//Sets layout type
type: 'HierarchicalTree',
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[LayoutAnimation, HierarchicalTree]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById('diagram') as HTMLElement);
root.render(<App />);Layout Updated Event
The layoutUpdated event fires at both the beginning and completion of the layout rendering process. This event enables tracking of layout calculation progress and provides timing information for performance monitoring or progress indication purposes.
The event includes a state parameter that indicates whether the layout process is starting or finishing, allowing developers to implement loading indicators, measure layout performance, or coordinate with other application components that depend on layout completion.
function handleLayoutUpdated(args){
if (args.state === 'Started') {
console.log('Layout started rendering');
}
}
<DiagramComponent id="diagram" width={'100%'} height={'550px'}
nodes={nodes} connectors={connectors}
layout=
// Event Triggers when the state of the layout rendering changes
layoutUpdated={handleLayoutUpdated}>
{/* Inject necessary services for the diagram */}
<Inject services={[HierarchicalTree]} />
</DiagramComponent>These layout events work together to provide comprehensive control over the automatic layout life cycle, from initial data loading through final rendering completion. They enable developers to create responsive, interactive diagram experiences with proper feedback and customization capabilities.