Layout events in Angular Diagram control
23 Aug 202513 minutes to read
Layout events in the Angular 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.
import { Component, ViewChild } from '@angular/core';
import { DiagramComponent, IDataLoadedEventArgs } from '@syncfusion/ej2-angular-diagrams';
<ejs-diagram #diagram id="diagram" width="100%" height="600px" [nodes]="nodes" [connectors]="connectors"
[layout]="layout" (dataLoaded)="dataLoaded($event)" > </ejs-diagram>
export class AppComponent {
@ViewChild("diagram")
public diagram!: DiagramComponent;
public dataLoaded(args: IDataLoadedEventArgs): void {
// Access the diagram instance and perform post-load customizations
console.log('Data loaded successfully:', args);
// Example: Apply custom styling to root nodes
// Custom logic here
}
}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 { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, NodeModel, ConnectorModel, LayoutModel, HierarchicalTree, DiagramModule,
HierarchicalTreeService, IExpandStateChangeEventArgs } from '@syncfusion/ej2-angular-diagrams';
Diagram.Inject(HierarchicalTree);
@Component({
imports: [DiagramModule],
providers: [HierarchicalTreeService],
standalone: true,
selector: "app-container",
template: `
<ejs-diagram #diagram id="diagram" width="100%" height="550px" [nodes]="nodes" [connectors]="connectors"
[layout]="layout" (expandStateChange)="expandStateChange($event)" > </ejs-diagram>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild("diagram")
public diagram!: DiagramComponent;
public layout: LayoutModel = {};
//Initialize nodes
public 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' }],
},
];
//Initialize connectors
public connectors: ConnectorModel[] = [{
// Unique name for the connector
id: 'connector1',
sourceID: 'Start',
targetID: 'Init',
type: 'Orthogonal',
}];
// Handle expand/collapse state changes
public expandStateChange(args: IExpandStateChangeEventArgs) {
//We can get the expanded or collapsed state in args
console.log('Expanded ' + args.state);
}
ngOnInit(): void {
//Uses layout to auto-arrange nodes on the Diagram page
this.layout = {
//Sets layout type
type: 'HierarchicalTree',
}
}
};import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));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 { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, NodeModel, ConnectorModel, LayoutModel, HierarchicalTree, DiagramModule,
HierarchicalTreeService, LayoutAnimation, LayoutAnimationService, ShapeStyleModel } from '@syncfusion/ej2-angular-diagrams';
Diagram.Inject(HierarchicalTree, LayoutAnimation);
@Component({
imports: [DiagramModule],
providers: [HierarchicalTreeService, LayoutAnimationService],
standalone: true,
selector: "app-container",
template: `
<ejs-diagram #diagram id="diagram" width="100%" height="600px" [nodes]="nodes" [connectors]="connectors"
[layout]="layout" (animationComplete)="animationComplete()" > </ejs-diagram>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild("diagram")
public diagram!: DiagramComponent;
public layout: LayoutModel = {};
//Initialize nodes
public 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' }],
},
];
//Initialize connectors
public 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',
},
];
// Handle animation state changes
public animationComplete() {
console.log('Animation complete');
(this.diagram.nodes[0].style as ShapeStyleModel).fill =
(this.diagram.nodes[0].style as ShapeStyleModel).fill === '#6BA5D7' ? 'red' : '#6BA5D7';
this.diagram.dataBind();
//customize
}
ngOnInit(): void {
//Uses layout to auto-arrange nodes on the Diagram page
this.layout = {
//Sets layout type
type: 'HierarchicalTree',
}
}
};import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));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.
import { Component, ViewChild } from '@angular/core';
import { DiagramComponent, ILayoutUpdatedEventArgs } from '@syncfusion/ej2-angular-diagrams';
<ejs-diagram #diagram id="diagram" width="100%" height="550px" [nodes]="nodes" [connectors]="connectors"
[layout]="layout" (layoutUpdated)="layoutUpdated($event)" > </ejs-diagram>
export class AppComponent {
@ViewChild("diagram")
public diagram!: DiagramComponent;
// Handle layout updated event for progress tracking
public layoutUpdated(args: ILayoutUpdatedEventArgs): void {
if (args.state === 'Started') {
console.log('Layout calculation started');
// Show loading indicator
} else if (args.state === 'Completed') {
console.log('Layout rendering completed');
// Hide loading indicator, perform post-layout actions
}
}
}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.