Serialization in Vue Diagram component

14 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.

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

The following code illustrates how to save the diagram:

//returns serialized string of the Diagram
const 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

Diagram is loaded from the serialized string data by client-side method, 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.

<ejs-diagram id="diagram" :width='width' :height='height' :loaded='loaded'>
</ejs-diagram>

export default {
  name: 'App',
  components: {
    'ejs-diagram': DiagramComponent,
  },
  data () {
    return {
      width: "100%",
      height: "700px",
      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:

let diagram: Diagram = new Diagram({
 serializationSettings: { preventDefaults: true },
});

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.

<template>
    <div id="app">
  
      <ejs-uploader ref="uploadObj" id="defaultfileupload" name="UploadFiles" :asyncSettings="path"
        :success="onUploadSuccess"></ejs-uploader>
      <button v-on:click="saveDiagram">Save Diagram</button>
  
      <ejs-diagram id="diagram" ref="diagramObj" :width="width" :height="height" :nodes="nodes"></ejs-diagram>
  
    </div>
  </template>
  
  <script setup>
  import { ref, onMounted } from "vue";
  import { DiagramComponent as EjsDiagram } from '@syncfusion/ej2-vue-diagrams';
  import { UploaderComponent as EjsUploader } from '@syncfusion/ej2-vue-inputs';
  
  let diagramInstance;
  let diagramObj = ref(null);
  
  // Data properties
  const nodes = [
    {
      id: 'Start',
      width: 140,
      height: 50,
      offsetX: 300,
      offsetY: 150,
      annotations: [{ id: 'label1', content: 'Start' }],
      shape: { type: 'Flow', shape: 'Terminator' }
    },
  ];
  
  const width = "1000px";
  const height = "590px";
  
  const path = {
    saveUrl:
      'https://services.syncfusion.com/vue/production/api/FileUploader/Save',
    removeUrl:
      'https://services.syncfusion.com/vue/production/api/FileUploader/Remove',
  };
  
  
  onMounted(function () {
    diagramInstance = diagramObj.value.ej2Instances;
  })
  
  // Handle file upload success
  const onUploadSuccess = (args) => {
    const file = args.file.rawFile;
    const reader = new FileReader();
    reader.readAsText(file);
    reader.onloadend = loadDiagram;
  }
  
  // Load diagram data from file
  const loadDiagram = (event) => {
    const jsonString = event.target.result;
    diagramInstance.loadDiagram(jsonString);
  }
  
  // Download diagram as a JSON file
  const download = (data) => {
    if (window.navigator.msSaveBlob) {
      const blob = new Blob([data], { type: 'data:text/json;charset=utf-8,' });
      window.navigator.msSaveBlob(blob, 'Diagram.json');
    } else {
      const dataStr = 'data:text/json;charset=utf-8,' + encodeURIComponent(data);
      const a = document.createElement('a');
      a.href = dataStr;
      a.download = 'Diagram.json';
      document.body.appendChild(a);
      a.click();
      a.remove();
    }
  }
  
  // Save the diagram
  const saveDiagram = () => {
    const diagramData = diagramInstance.saveDiagram();
    download(diagramData);
  }
  
  </script>
  
  <style>
  @import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
  </style>
<template>
    <div id="app">
        
        <ejs-uploader ref="uploadObj" id="defaultfileupload" name="UploadFiles" :asyncSettings="path"
            :success="onUploadSuccess" ></ejs-uploader>
        <button v-on:click="saveDiagram">Save Diagram</button>

        <ejs-diagram id="diagram" ref="diagramObj" :width="width" :height="height" :nodes="nodes"></ejs-diagram>
    </div>
</template>

<script>
import { DiagramComponent } from '@syncfusion/ej2-vue-diagrams';
import { UploaderComponent } from '@syncfusion/ej2-vue-inputs';

var diagramInstance;
var nodes = [
    {
        id: 'Start',
        width: 140,
        height: 50,
        offsetX: 300,
        offsetY: 150,
        annotations: [{ id: 'label1', content: 'Start' }],
        shape: { type: 'Flow', shape: 'Terminator' },
    },
];

export default {
    name: 'App',
    components: {
        'ejs-diagram': DiagramComponent,
        'ejs-uploader': UploaderComponent,
    },
    data() {
        return {
            width: '100%',
            height: '650px',
            nodes: nodes,
            path: {
                saveUrl:
                    'https://services.syncfusion.com/vue/production/api/FileUploader/Save',
                removeUrl:
                    'https://services.syncfusion.com/vue/production/api/FileUploader/Remove',
            }
        };
    },
    methods: {
        // Handle file upload success
        onUploadSuccess(args) {
            const file = args.file.rawFile;
            const reader = new FileReader();
            reader.readAsText(file);
            reader.onloadend = this.loadDiagram;
        },

        // Load diagram data from file
        loadDiagram(event) {
            const jsonString = event.target.result;
            diagramInstance.loadDiagram(jsonString);
        },

        // Download diagram as a JSON file
        download(data) {
            if (window.navigator.msSaveBlob) {
                const blob = new Blob([data], {
                    type: 'data:text/json;charset=utf-8,',
                });
                window.navigator.msSaveBlob(blob, 'Diagram.json');
            } else {
                const dataStr =
                    'data:text/json;charset=utf-8,' + encodeURIComponent(data);
                const a = document.createElement('a');
                a.href = dataStr;
                a.download = 'Diagram.json';
                document.body.appendChild(a);
                a.click();
                a.remove();
            }
        },

        // Save the diagram
        saveDiagram() {
            const diagramData = diagramInstance.saveDiagram();
            this.download(diagramData);
        },
    },
    mounted: function () {
        diagramInstance = this.$refs.diagramObj.ej2Instances;
    }
};

</script>

<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
</style>

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.

<template>
    <div id="app">

        <button v-on:click="loadMermaidFlowchart">Load</button>

        <ejs-diagram id="diagram" ref="diagramObj" :width="width" :height="height" :layout="layout"
            :getNodeDefaults="getNodeDefaults" :getConnectorDefaults="getConnectorDefaults"></ejs-diagram>

    </div>
</template>

<script setup>
import { provide, ref, onMounted } from "vue";
import { DiagramComponent as EjsDiagram, FlowchartLayout } from '@syncfusion/ej2-vue-diagrams';

let diagramInstance;
let diagramObj = ref(null);

const width = "1000px";
const height = "590px";

//Sets layout type
const layout = { type: 'Flowchart' }

//Sets the default properties for nodes and connectors
const getNodeDefaults = (node) => {
    node.width = 120;
    node.height = 50;
    if ((node.shape).shape === 'Decision') {
        node.height = 80;
    }
    (node.annotations[0].style).bold = true;
    return node;
}

const getConnectorDefaults = (connector) => {
    connector.type = 'Orthogonal';
    connector.style.strokeColor = '#6CA0DC';
    connector.targetDecorator.style = { fill: '#6CA0DC', strokeColor: '#6CA0DC' };
    return connector;
}

onMounted(function () {
    diagramInstance = diagramObj.value.ej2Instances;
})

const 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 mindmap data to diagram
    //parameter: mermaidMindmapData - mermaid format string data for mindmap
    diagramInstance.loadDiagramFromMermaid(mermaidFlowchartData);
}

provide('diagram', [FlowchartLayout]);
</script>

<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
</style>
<template>
    <div id="app">

        <button v-on:click="loadMermaidFlowchart">Load</button>

        <ejs-diagram id="diagram" ref="diagramObj" :width="width" :height="height" :layout="layout"
            :getNodeDefaults='getNodeDefaults' :getConnectorDefaults='getConnectorDefaults'></ejs-diagram>
    
    </div>
</template>

<script>
import { DiagramComponent, FlowchartLayout, } from '@syncfusion/ej2-vue-diagrams';

var diagramInstance;
var nodes = [];

export default {
    name: 'App',
    components: {
        'ejs-diagram': DiagramComponent,
    },
    data() {
        return {
            width: '100%',
            height: '650px',

            //Sets layout type
            layout: { type: 'Flowchart' },

            //Sets the default properties for nodes and connectors
            getNodeDefaults(node) {
                node.width = 120;
                node.height = 50;
                if ((node.shape).shape === 'Decision') {
                    node.height = 80;
                }
                (node.annotations[0].style).bold = true;
                return node;
            },

            getConnectorDefaults(connector) {
                connector.type = 'Orthogonal';
                connector.style.strokeColor = '#6CA0DC';
                connector.targetDecorator.style = { fill: '#6CA0DC', strokeColor: '#6CA0DC' };
                return connector;
            },
        };
    },
    methods: {
        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
            diagramInstance.loadDiagramFromMermaid(mermaidFlowchartData);
        }
    },
    mounted: function () {
        diagramInstance = this.$refs.diagramObj.ej2Instances;
    },
    provide: { diagram: [FlowchartLayout] }
};

</script>

<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
</style>

Load mindmap layout

The following example shows how to load mind map diagram from mermaid syntax.

<template>
    <div id="app">

        <button v-on:click="loadMermaidMindmap">Load</button>

        <ejs-diagram id="diagram" ref="diagramObj" :width="width" :height="height" :layout="layout"
            :getNodeDefaults="getNodeDefaults" :getConnectorDefaults="getConnectorDefaults"></ejs-diagram>

    </div>
</template>

<script setup>
import { provide, ref, onMounted } from "vue";
import { DiagramComponent as EjsDiagram, MindMap } from '@syncfusion/ej2-vue-diagrams';

let diagramInstance;
let diagramObj = ref(null);

const width = "1000px";
const height = "590px";

//Sets layout type
const layout = {
    type: 'MindMap',
    verticalSpacing: 50,
    horizontalSpacing: 50,
    orientation: 'Horizontal',
}

//Sets the default properties for nodes and connectors
const getNodeDefaults = (node) => {
    node.width = 120;
    node.height = 50;
    node.annotations[0].style.bold = true;
    return node;
}

const getConnectorDefaults = (connector) => {
    connector.type = 'Orthogonal';
    connector.style.strokeColor = '#6CA0DC';
    connector.targetDecorator.shape = 'None';
    return connector;
}

onMounted(function () {
    diagramInstance = diagramObj.value.ej2Instances;
})

const loadMermaidMindmap = () => {
    const mermaidMindmapData = `mindmap
                                      root((mindmap))
                                        Origins
                                          Popularisation
                                        Research
                                          On effectivness 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
    diagramInstance.loadDiagramFromMermaid(mermaidMindmapData);
}

provide('diagram', [MindMap]);
</script>

<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
</style>
<template>
    <div id="app">

        <button v-on:click="loadMermaidMindmap">Load</button>

        <ejs-diagram id="diagram" ref="diagramObj" :width="width" :height="height" :layout="layout"
            :getNodeDefaults="getNodeDefaults" :getConnectorDefaults="getConnectorDefaults"></ejs-diagram>

    </div>
</template>

<script>
import { DiagramComponent, MindMap } from '@syncfusion/ej2-vue-diagrams';

var diagramInstance;
var nodes = [];

export default {
    name: 'App',
    components: {
        'ejs-diagram': DiagramComponent,
    },
    data() {
        return {
            width: '100%',
            height: '650px',
            //Sets layout type
            layout: {
                type: 'MindMap',
                verticalSpacing: 50,
                horizontalSpacing: 50,
                orientation: 'Horizontal',
            },

            //Sets the default properties for nodes and connectors
            getNodeDefaults(node) {
                node.width = 120;
                node.height = 50;
                node.annotations[0].style.bold = true;
                return node;
            },

            getConnectorDefaults(connector) {
                connector.type = 'Orthogonal';
                connector.style.strokeColor = '#6CA0DC';
                connector.targetDecorator.shape = 'None';
                return connector;
            },

        };
    },
    methods: {
        loadMermaidMindmap() {
            const mermaidMindmapData = `mindmap
                                    root((mindmap))
                                      Origins
                                        Popularisation
                                      Research
                                        On effectivness 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
            diagramInstance.loadDiagramFromMermaid(mermaidMindmapData);
        },
    },
    mounted: function () {
        diagramInstance = this.$refs.diagramObj.ej2Instances;
    },
    provide: { diagram: [MindMap] },
};
</script>

<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
</style>

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.