Serialization in React Diagram component
6 Dec 202424 minutes to read
Serialization is the process of converting the state of the diagram into a format that can be saved and later restored. This ensures that the diagram’s current state, including its nodes, connectors, and configurations, can be persisted across sessions.
Serialization involves saving the diagram’s state as a JSON string, which can then be stored in a database, file, or other storage medium. When needed, the serialized string can be deserialized to recreate the diagram in its previous state.
To easily save the contents of the diagram as a JSON string or file stream, and load it from the saved file, refer to the video link below.
Save
The diagram is serialized as string while saving. The client-side method, saveDiagram
, helps to serialize the diagram as a string. This method captures the entire diagram’s configuration and content, converting it into a string representation.
The following code illustrates how to save the diagram:
let saveData: string;
//returns serialized string of the Diagram
saveData = diagramInstance.saveDiagram();
This JSON string can be stored in local storage for future use. The following code illustrates how to save the serialized string into local storage and how to retrieve it:
//Saves the string in to local storage
localStorage.setItem('fileName', saveData);
// Retrieve the saved string from local storage
saveData = localStorage.getItem('fileName');
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
section.
Load
The diagram can be loaded from serialized string data using the loadDiagram
method. The saved string should be passed as the parameter of the loadDiagram method. The following code illustrates how to load the diagram from serialized string data:
/*
* 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)
*/
diagramInstance.loadDiagram(saveData);
Note: Before loading a new diagram, existing diagram is cleared.
Loaded Event
The loaded
event triggers when all diagram elements are loaded using loadDiagram
method. You can use this event to customize diagram elements during the loading process.
return (
loaded={(args) => {
//You can use this event to customize diagram elements during the loading process
}}/>
)
The event has two arguments such as name, diagram
name
Type: String
Description: Returns the event name.
diagram
Type: Diagram
Description: Returns the diagram model properties.
Users can perform customizations or modifications to the diagram elements once the loading process is complete.
Prevent Default Values
The preventDefaults
property of serializationSettings
is used to simplify the saved JSON object by excluding default properties that are inherent to the diagram. This helps reduce the size of the serialized data and improves efficiency when saving and loading diagrams.
By enabling preventDefaults, only properties that you set in diagram are included in the serialized JSON object. This optimization is useful for scenarios where minimizing data size is crucial, such as in applications with large diagrams or when optimizing network transfers.
The following code illustrates how to enable the preventDefaults property to simplify the JSON object:
return (
<div>
<DiagramComponent
serializationSettings =
></DiagramComponent>
</div>
)
Save and load diagram using uploader control
The JSON files can be uploaded using the uploader component, where they are parsed to extract the JSON data they contain. To achieve this, configure the uploader component with the saveUrl property to receive uploaded files and store them on the server. Similarly, use the removeUrl property to handle file removal operations on the server.
When a JSON file is uploaded, it undergoes parsing to extract its JSON data. This data is then loaded into the diagram using the loadDiagram
method.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { DiagramComponent } from '@syncfusion/ej2-react-diagrams';
import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
export default function App() {
let diagramInstance;
// Initialize Uploader Object
let uploadObject = {
saveUrl:
'https://services.syncfusion.com/js/production/api/FileUploader/Save',
removeUrl:
'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
}
// Callback function for when the upload is successful
function onUploadSuccess(args) {
var file = args.file.rawFile;
var reader = new FileReader();
reader.readAsText(file);
reader.onloadend = loadDiagram;
}
// Function to load the diagram from the uploaded file
function loadDiagram(event) {
diagramInstance.loadDiagram(event.target.result);
}
// Function to save the current diagram
function saveDiagram() {
download(diagramInstance.saveDiagram());
}
// Function to download the diagram data as a JSON file
function download(data) {
if (window.navigator.msSaveBlob) {
let blob = new Blob([data], { type: 'data:text/json;charset=utf-8,' });
window.navigator.msSaveBlob(blob, 'Diagram.json');
} else {
let dataStr = 'data:text/json;charset=utf-8,' + encodeURIComponent(data);
let a = document.createElement('a');
a.href = dataStr;
a.download = 'Diagram.json';
document.body.appendChild(a);
a.click();
a.remove();
}
}
// Initialize nodes for the diagram
let nodes = [
{
id: 'Start',
width: 140,
height: 50,
offsetX: 300,
offsetY: 50,
annotations: [{ id: 'label1', content: 'Start' }],
shape: { type: 'Flow', shape: 'Terminator' }
},
];
return (
// Initialize Diagram component
<div>
<label>Browse to load</label>
<UploaderComponent asyncSettings={uploadObject} success={onUploadSuccess} />
<ButtonComponent content="Save Diagram" onClick={saveDiagram} />
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={nodes}
></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, NodeModel } from '@syncfusion/ej2-react-diagrams';
import { UploaderComponent, FileInfo } from '@syncfusion/ej2-react-inputs';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
export default function App() {
let diagramInstance: DiagramComponent;
// Initialize Uploader Object
let uploadObject = {
saveUrl:
'https://services.syncfusion.com/js/production/api/FileUploader/Save',
removeUrl:
'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
}
// Callback function for when the upload is successful
function onUploadSuccess(args: { file: FileInfo }) {
var file: any = args.file.rawFile;
var reader = new FileReader();
reader.readAsText(file);
reader.onloadend = loadDiagram;
}
// Function to load the diagram from the uploaded file
function loadDiagram(event: any) {
diagramInstance.loadDiagram(event.target.result);
}
// Function to save the current diagram
function saveDiagram() {
download(diagramInstance.saveDiagram());
}
// Function to download the diagram data as a JSON file
function download(data: string) {
if ((window.navigator as any).msSaveBlob) {
let blob = new Blob([data], { type: 'data:text/json;charset=utf-8,' });
(window.navigator as any).msSaveBlob(blob, 'Diagram.json');
} else {
let dataStr = 'data:text/json;charset=utf-8,' + encodeURIComponent(data);
let a: HTMLAnchorElement = document.createElement('a');
a.href = dataStr;
a.download = 'Diagram.json';
document.body.appendChild(a);
a.click();
a.remove();
}
}
// Initialize nodes for the diagram
let nodes: NodeModel[] = [
{
id: 'Start',
width: 140,
height: 50,
offsetX: 300,
offsetY: 50,
annotations: [{ id: 'label1', content: 'Start' }],
shape: { type: 'Flow', shape: 'Terminator' }
},
];
return (
// Initialize Diagram component
<div>
<UploaderComponent asyncSettings={uploadObject} success={onUploadSuccess} />
<ButtonComponent content="Save Diagram" onClick={saveDiagram} />
<DiagramComponent
id="container"
ref={(diagram: any) => (diagramInstance = diagram)}
width={'100%'}
height={'600px'}
nodes={nodes}
/>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram") as HTMLElement);
root.render(<App />);
Importing and Exporting Mind Map and Flowchart Diagrams using Mermaid Syntax
The Diagram
supports saving diagrams in Mermaid syntax format. Mermaid is a Markdown-inspired syntax that automatically generates diagrams. With this functionality, you can easily create mind maps and flowcharts from Mermaid syntax data, simplifying the visualization of complex ideas and processes without manual drawing. Additionally, you can export your mind maps and flowcharts to Mermaid syntax, allowing for easy sharing, editing, and use across different platforms.
Save diagram as Mermaid syntax
The saveDiagramAsMermaid
method serializes the diagram into a Mermaid-compatible string format. This method is specifically designed for diagrams that utilize Flowchart and Mind map layouts. The following code illustrates how to save the diagram in Mermaid string format.
//returns the serialized Mermaid string of the Diagram
let data = diagramInstance.saveDiagramAsMermaid();
Load diagram from Mermaid syntax
You can load a diagram
from the serialized Mermaid syntax data using the loadDiagramFromMermaid
method. The following code illustrates how to load a diagram from a Mermaid string data.
Load flowchart layout
The following example shows how to load flowchart diagram from mermaid syntax.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { DiagramComponent, Inject, FlowchartLayout } from "@syncfusion/ej2-react-diagrams";
export default function App() {
let diagramInstance;
// Mermaid syntax for the flowchart data
let 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;`;
// Function to set default properties for nodes
function getNodeDefaults(node) {
node.width = 120;
node.height = 50;
if (node.shape.shape === 'Decision') {
node.height = 80;
}
node.annotations[0].style.bold = true;
return node;
};
// Function to set default properties for connectors
function getConnectorDefaults(connector) {
connector.type = 'Orthogonal';
return connector;
};
// Function to load the Mermaid flowchart data into the diagram
function loadMermaidFlowchart() {
diagramInstance.loadDiagramFromMermaid(mermaidFlowchartData);
};
return (
// Initialize Diagram component
<div>
<button onClick={loadMermaidFlowchart} id="loadMermaidFlowchart">Load Mermaid Flowchart</button>
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={"100%"}
height={"600px"}
layout={{ type: 'Flowchart' }}
getNodeDefaults={getNodeDefaults}
getConnectorDefaults={getConnectorDefaults}
>
<Inject services={[FlowchartLayout]} />
</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, FlowchartLayout, ConnectorModel, NodeModel } from "@syncfusion/ej2-react-diagrams";
export default function App() {
let diagramInstance: DiagramComponent;
// Mermaid syntax for the flowchart data
let mermaidFlowchartData: string = `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;`;
// Function to set default properties for nodes
function getNodeDefaults(node: NodeModel | any): NodeModel {
node.width = 120;
node.height = 50;
if (node.shape.shape === 'Decision') {
node.height = 80;
}
node.annotations[0].style.bold = true;
return node;
};
// Function to set default properties for connectors
function getConnectorDefaults(connector: ConnectorModel): ConnectorModel {
connector.type = 'Orthogonal';
return connector;
};
// Function to load the Mermaid flowchart data into the diagram
function loadMermaidFlowchart(): void {
diagramInstance.loadDiagramFromMermaid(mermaidFlowchartData);
};
return (
// Initialize Diagram component
<div>
<button onClick={loadMermaidFlowchart} id="loadMermaidFlowchart">Load Mermaid Flowchart</button>
<DiagramComponent
id="container"
ref={(diagram: any) => (diagramInstance = diagram)}
width={"100%"}
height={"600px"}
layout={{ type: 'Flowchart' }}
getNodeDefaults={getNodeDefaults}
getConnectorDefaults={getConnectorDefaults}
>
<Inject services={[FlowchartLayout]} />
</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 />);
Load mindmap layout
The following example shows how to load mind map diagram from mermaid syntax.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { DiagramComponent, Inject, MindMap } from "@syncfusion/ej2-react-diagrams";
export default function App() {
let diagramInstance;
// Mermaid syntax for the mindmap data
let mermaidMindmapData = `mindmap
root((mindmap))
Origins
Popularisation
Research
On effectiveness<br/>and features
On Automatic creation
Tools
Pen and paper
Mermaid`;
// Function to set default properties for nodes
function getNodeDefaults(node) {
node.width = 140;
node.height = 50;
node.annotations[0].style.bold = true;
return node;
};
// Function to set default properties for connectors
function getConnectorDefaults(connector) {
connector.type = 'Orthogonal';
return connector;
};
// Function to load the Mermaid mindmap data into the diagram
function loadMermaidMindmap() {
diagramInstance.loadDiagramFromMermaid(mermaidMindmapData);
};
return (
// Initialize Diagram component
<div>
<button onClick={loadMermaidMindmap} id="loadMermaidMindmap">Load Mermaid Mindmap</button>
<DiagramComponent
id="container"
ref={(diagram) => (diagramInstance = diagram)}
width={"100%"}
height={"350px"}
layout={{
type: 'MindMap',
verticalSpacing: 50,
horizontalSpacing: 50,
orientation: 'Horizontal',
}}
getNodeDefaults={getNodeDefaults}
getConnectorDefaults={getConnectorDefaults}
>
<Inject services={[MindMap]} />
</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, MindMap, NodeModel, ConnectorModel } from "@syncfusion/ej2-react-diagrams";
export default function App() {
let diagramInstance: DiagramComponent;
// Mermaid syntax for the mindmap data
let mermaidMindmapData: string = `mindmap
root((mindmap))
Origins
Popularisation
Research
On effectiveness<br/>and features
On Automatic creation
Tools
Pen and paper
Mermaid`;
// Function to set default properties for nodes
function getNodeDefaults(node: NodeModel | any): NodeModel {
node.width = 140;
node.height = 50;
node.annotations[0].style.bold = true;
return node;
};
// Function to set default properties for connectors
function getConnectorDefaults(connector: ConnectorModel): ConnectorModel {
connector.type = 'Orthogonal';
return connector;
};
// Function to load the Mermaid mindmap data into the diagram
function loadMermaidMindmap() {
diagramInstance.loadDiagramFromMermaid(mermaidMindmapData);
};
return (
// Initialize Diagram component
<div>
<button onClick={loadMermaidMindmap} id="loadMermaidMindmap">Load Mermaid Mindmap</button>
<DiagramComponent
id="container"
ref={(diagram: any) => (diagramInstance = diagram)}
width={"100%"}
height={"350px"}
layout={{ type: 'MindMap', orientation: 'Horizontal' }}
getNodeDefaults={getNodeDefaults}
getConnectorDefaults={getConnectorDefaults}
>
<Inject services={[MindMap]} />
</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 />);
Note: Mermaid syntax data serialization and deserialization are only supported for Flowchart and Mind map layouts. Please ensure that your diagram uses one of these layouts to successfully load the data.