Save and Load Diagrams in Angular Diagram Component
25 Aug 202518 minutes to read
Serialization is the process of converting the diagram’s current state into a storage format that can be saved and later restored. This feature ensures that all diagram elements, including nodes, connectors, and their configurations, persist across application sessions.
The serialization process converts the diagram into a JSON string format, which can be stored in databases, files, or other storage systems. When needed, this serialized data can be deserialized to recreate the diagram exactly as it was previously configured.
Use serialization when you need to:
- Save user-created diagrams for future editing
- Implement undo/redo functionality
- Create diagram templates
- Transfer diagrams between different sessions or users
To save and load the diagram in Angular, refer to the below video link.
Saving Diagrams
Basic Save Operation
The saveDiagram
method serializes the entire diagram configuration into a JSON string. This method captures all diagram elements, their properties, and the current state.
//returns serialized string of the Diagram
saveData = this.diagram.saveDiagram();
The serialized JSON string can be stored in various storage systems. The following example demonstrates local storage implementation:
//Saves the string in to local storage
localStorage.setItem('fileName', saveData);
// Retrieve the saved string from local storage
saveData = localStorage.getItem('fileName');
Alternative Save Formats
The diagram can also be saved as raster or vector image files. For more information about saving the diagram as images, refer to the Print
and Export
sections.
Loading Diagrams
Basic Load Operation
The loadDiagram
method recreates the diagram from serialized JSON data. This method accepts the previously saved JSON string as a parameter.
export class AppComponent {
@ViewChild('diagram', { static: true }) diagram: DiagramComponent;
loadDiagram(): void {
const savedData: string = localStorage.getItem('diagramData');
if (savedData) {
/*
* Loads the diagram from saved JSON data.
* parameter 1 - The string representing the diagram model JSON to be loaded.
* parameter 2 - Whether it is ej1 data or not (optional)
*/
this.diagram.loadDiagram(savedData);
console.log('Diagram loaded successfully');
} else {
console.warn('No saved diagram data found');
}
}
}
NOTE
Before loading a new diagram, the existing diagram content is automatically cleared.
Handling Load Completion
The loaded
event triggers when all diagram elements finish loading through the loadDiagram
method. Use this event to perform post-load customizations or validations.
<ejs-diagram #diagram id="diagram" width="100%" height="700px" (loaded)="loaded()" >
</ejs-diagram>
export class AppComponent {
public loaded(args:ILoadedEventArgs): void {
//You can use this event to customize diagram elements during the loading process
}
}
The loaded event provides the following arguments:
name
- Type: String
- Description: Returns the event name
diagram
- Type: Diagram
- Description: Returns the complete diagram model with all properties
Optimizing Serialized Data
Preventing Default Values
The preventDefaults
property within serializationSettings
reduces the size of serialized data by excluding default properties. This optimization improves performance when handling large diagrams or frequent save operations.
When enabled, only explicitly set properties are included in the JSON output, significantly reducing file size and improving load times.
<ejs-diagram #diagram id="diagram" width="100%" height="700px" (serializationSettings)="serializationSettings" >
</ejs-diagram>
export class AppComponent {
public serializationSettings: SerializationSettingsModel = {};
ngOnInit() {
this.serializationSettings = { preventDefaults: true };
}
}
File-Based Save and Load Operations
Using Uploader Component
JSON files can be uploaded and processed using the uploader component. Configure the uploader with appropriate server endpoints to handle file operations, then parse the uploaded JSON data to load diagrams.
The uploader requires:
-
saveUrl
property for receiving and storing uploaded files -
removeUrl
property for handling file deletion operations - File parsing logic to extract JSON data from uploaded files
import { ViewChild, Component, ViewEncapsulation } from '@angular/core';
import { DiagramComponent, DiagramModule } from '@syncfusion/ej2-angular-diagrams';
import { Uploader, FileInfo } from '@syncfusion/ej2-inputs';
import { NodeModel } from '@syncfusion/ej2-diagrams';
@Component({
imports: [DiagramModule],
providers: [],
standalone: true,
selector: 'app-container',
template: ` <div> <input id="fileupload" type="file" />
<button (click)="onSaveClick()">Save Diagram</button> </div>
<ejs-diagram #diagram id="diagram" width="100%" height="600px" [nodes]="nodes" > </ejs-diagram>`,
encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
@ViewChild("diagram")
public diagram!: DiagramComponent;
public uploadObject: Uploader;
public nodes: NodeModel[] = [];
constructor() {
this.uploadObject = new Uploader({
asyncSettings: {
saveUrl:
'https://services.syncfusion.com/js/production/api/FileUploader/Save',
removeUrl:
'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
},
success: this.onUploadSuccess.bind(this),
});
}
ngOnInit() {
// Initialize nodes
this.nodes = [
{
id: 'Start',
width: 140,
height: 50,
offsetX: 300,
offsetY: 50,
annotations: [{ id: 'label1', content: 'Start' }],
shape: { type: 'Flow', shape: 'Terminator' },
},
];
}
ngAfterViewInit() {
this.uploadObject.appendTo('#fileupload');
}
onUploadSuccess(args: { file: FileInfo }) {
const file: any = args.file.rawFile;
const reader = new FileReader();
reader.readAsText(file);
reader.onloadend = this.loadDiagram.bind(this);
}
loadDiagram(event: ProgressEvent<FileReader>) {
const jsonString = event.target?.result as string;
this.diagram.loadDiagram(jsonString);
}
download(data: string): void {
if ((window.navigator as any).msSaveBlob) {
const blob: any = new Blob([data], {
type: 'data:text/json;charset=utf-8,',
});
(window.navigator as any).msSaveBlob(blob, 'Diagram.json');
} else {
const dataStr: string =
'data:text/json;charset=utf-8,' + encodeURIComponent(data);
const a: HTMLAnchorElement = document.createElement('a');
a.href = dataStr;
a.download = 'Diagram.json';
document.body.appendChild(a);
a.click();
a.remove();
}
}
onSaveClick() {
this.download(this.diagram.saveDiagram());
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Mermaid Syntax Integration
Overview
The Diagram
component supports importing and exporting diagrams using Mermaid syntax. Mermaid is a markdown-inspired syntax for creating diagrams programmatically, enabling easy diagram creation and sharing across different platforms.
This functionality supports:
- Mind maps
- Flowcharts
- UML sequence diagrams
Saving Diagrams as Mermaid Syntax
The saveDiagramAsMermaid
method converts compatible diagrams into Mermaid syntax format. This method works specifically with Flowchart and Mind map layouts.
//returns the serialized Mermaid string of the Diagram
data = this.diagram.saveDiagramAsMermaid();
Loading Diagrams from Mermaid Syntax
The loadDiagramFromMermaid
method creates diagrams from Mermaid syntax data, automatically generating the appropriate layout and styling.
Loading Flowchart Layout
The following example demonstrates loading a flowchart diagram from Mermaid syntax:
import { Component, ViewChild, ViewEncapsulation } from '@angular/core';
import { DiagramComponent, DiagramModule } from '@syncfusion/ej2-angular-diagrams';
import { Diagram, NodeModel, ConnectorModel, FlowShapeModel, FlowchartLayout } from '@syncfusion/ej2-diagrams';
Diagram.Inject(FlowchartLayout);
@Component({
imports: [
DiagramModule
],
providers: [],
standalone: true,
selector: "app-container",
template: `
<button (click)="loadMermaidFlowchart()">Load</button>
<ejs-diagram #diagram id="diagram" width="100%" height="600px" [getNodeDefaults]="getNodeDefaults"
[getConnectorDefaults]="getConnectorDefaults" [layout]="layout"> </ejs-diagram>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild("diagram")
public diagram!: DiagramComponent;
public getNodeDefaults(node: NodeModel): NodeModel {
node.width = 120;
node.height = 50;
if ((node.shape as FlowShapeModel).shape === 'Decision') {
node.height = 80;
}
return node;
}
public getConnectorDefaults(connector: ConnectorModel): ConnectorModel {
connector.type = 'Orthogonal';
return connector;
}
public layout = { type: 'Flowchart' }
public loadMermaidFlowchart() {
const mermaidFlowchartData = `flowchart TD
A[Start] --> B(Process)
B -.- C{Decision}
C --Yes--> D[Plan 1]
C ==>|No| E[Plan 2]
style A fill:#90EE90,stroke:#333,stroke-width:2px;
style B fill:#4682B4,stroke:#333,stroke-width:2px;
style C fill:#FFD700,stroke:#333,stroke-width:2px;
style D fill:#FF6347,stroke:#333,stroke-width:2px;
style E fill:#FF6347,stroke:#333,stroke-width:2px;`;
// load the mermaid flowchart data to diagram
//parameter: mermaidFlowchartData - mermaid format string data for flowchart
this.diagram.loadDiagramFromMermaid(mermaidFlowchartData);
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Loading Mind Map Layout
The following example demonstrates loading a mind map diagram from Mermaid syntax:
import { Component, ViewChild, ViewEncapsulation } from '@angular/core';
import { DiagramComponent, DiagramModule } from '@syncfusion/ej2-angular-diagrams';
import { Diagram, NodeModel, ConnectorModel, TextStyleModel, ShapeAnnotationModel,
DecoratorModel, StrokeStyleModel, MindMap } from '@syncfusion/ej2-diagrams';
Diagram.Inject(MindMap);
@Component({
imports: [
DiagramModule
],
providers: [],
standalone: true,
selector: "app-container",
template: `
<button (click)="loadMermaidMindmap()">Load</button>
<ejs-diagram #diagram id="diagram" width="100%" height="600px" [getNodeDefaults]="getNodeDefaults"
[getConnectorDefaults]="getConnectorDefaults" [layout]="layout"> </ejs-diagram>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild("diagram")
public diagram!: DiagramComponent;
public getNodeDefaults(node: NodeModel): NodeModel {
node.width = 120;
node.height = 50;
return node;
}
public getConnectorDefaults(connector: ConnectorModel): ConnectorModel {
connector.type = 'Orthogonal';
(connector.targetDecorator as DecoratorModel).shape = 'None';
return connector;
}
public layout = {
type: 'MindMap',
verticalSpacing: 50,
horizontalSpacing: 50,
orientation: 'Horizontal',
}
public loadMermaidMindmap() {
const mermaidMindmapData = `mindmap
root((mindmap))
Origins
Popularisation
Research
On effectivness<br/>and features
On Automatic creation
Tools
Pen and paper
Mermaid `;
// load the mermaid mindmap data to diagram
//parameter: mermaidMindmapData - mermaid format string data for mindmap
this.diagram.loadDiagramFromMermaid(mermaidMindmapData);
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Loading UML Sequence Diagram
The following example demonstrates loading a UML Sequence diagram from Mermaid syntax:
import { Component, ViewChild, ViewEncapsulation } from '@angular/core';
import { DiagramComponent, DiagramModule } from '@syncfusion/ej2-angular-diagrams';
@Component({
imports: [DiagramModule],
providers: [],
standalone: true,
selector: "app-container",
template: `
<button (click)="loadMermaidSeqDiagram()">Load Mermaid</button>
<ejs-diagram #diagram id="diagram" width="100%" height="600px"></ejs-diagram>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild("diagram")
public diagram!: DiagramComponent;
public loadMermaidSeqDiagram() {
const mermaidData: string = `
sequenceDiagram
participant User
participant Controller
participant Service
participant Database
User->>Controller: sendRequest()
activate Controller
Controller->>Service: processRequest()
activate Service
Service->>Database: queryData()
activate Database
Database-->>Service: returnData()
deactivate Database
Service-->>Controller: returnResponse()
deactivate Service
Controller-->>User: sendResponse()
deactivate Controller`;
// load the mermaid sequence diagram data to diagram
//parameter: mermaidData - mermaid format string data for UML Sequence Diagram
this.diagram.loadDiagramFromMermaid(mermaidData);
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
NOTE
Mermaid syntax-based serialization and deserialization supports only Flowchart layout, Mind map layout, and UML Sequence Diagram. Ensure that your Mermaid data aligns with one of these supported layouts for successful diagram loading.