Context menu in Vue Diagram component

12 Nov 202424 minutes to read

In a graphical user interface (GUI), a context menu is a type of menu that appears when you perform a right-click operation. It offers users a set of actions relevant to the current context. In diagrams, context menus can be customized extensively. The Diagram control provides built-in context menu items while also allowing users to define custom menu items through the contextMenuSettings property. This flexibility enables tailoring menus to specific application needs, including creating nested levels of menu items for more intricate user interactions.

NOTE

If you want to use contextMenu in diagram, you need to inject DiagramContextMenu Module in the diagram.

Default context menu

Diagram provides some default context menu items to ease the execution of some frequently used commands. The show property helps you to enable/disable the context menu. The following code illustrates how to enable the default context menu items.

<template>
    <div id="app">
        <ejs-diagram id="diagram" :width='width' :height='height' :nodes='nodes' :connectors='connectors'
            :contextMenuSettings='contextMenuSettings'></ejs-diagram>
    </div>
</template>
<script setup>
import { provide } from "vue";
import { DiagramComponent as EjsDiagram, DiagramContextMenu } from '@syncfusion/ej2-vue-diagrams';

let nodes = [{
    id: 'node1',
    width: 100,
    height: 100,
    offsetX: 100,
    offsetY: 100,
    annotations: [{
        id: 'label1',
        content: 'Rectangle1',
    }]
},
{
    id: 'node2',
    width: 100,
    height: 100,
    offsetX: 300,
    offsetY: 100,
    annotations: [{
        id: 'label2',
        content: 'Rectangle2',
    }]
}];

let connectors = [{
    id: 'connector1',
    sourceID: 'node1',
    targetID: 'node2',
    type: 'Straight',
}]

const width = "100%";
const height = "350px";
const contextMenuSettings = {
    //Enables the context menu
    show: true,
}

provide('diagram', [DiagramContextMenu]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/fabric.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-icons/styles/material.css';
</style>
<template>
    <div id="app">
        <ejs-diagram id="diagram" :width='width' :height='height' :nodes='nodes' :connectors='connectors'
            :contextMenuSettings='contextMenuSettings'></ejs-diagram>
    </div>
</template>
<script>
import { DiagramComponent, DiagramContextMenu } from '@syncfusion/ej2-vue-diagrams';

let nodes = [{
    id: 'node1',
    width: 100,
    height: 100,
    offsetX: 100,
    offsetY: 100,
    annotations: [{
        id: 'label1',
        content: 'Rectangle1',
    }]
},
{
    id: 'node2',
    width: 100,
    height: 100,
    offsetX: 300,
    offsetY: 100,
    annotations: [{
        id: 'label2',
        content: 'Rectangle2',
    }]
}];

let connectors = [{
    id: 'connector1',
    sourceID: 'node1',
    targetID: 'node2',
    type: 'Straight',
}];

export default {
    name: "App",
    components: {
        "ejs-diagram": DiagramComponent
    },
    data() {
        return {
            width: "100%",
            height: "350px",
            nodes: nodes,
            connectors: connectors,
            contextMenuSettings: {
                //Enables the context menu
                show: true,

            }
        }
    },
    provide: {
        diagram: [DiagramContextMenu]
    }
}
</script>
<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
</style>

Custom context menu

Context menus can be customized for individual nodes by defining specific menu items beyond the default options. To add additional context menu items, you need to define and incorporate them into the items property of the context menu.

Each custom item can be defined with specific text and ID using the text and ID properties, respectively. Additionally, you can enhance visual cues by associating icons through the iconCss for enabling the use of font icons. The target property specifies where each menu item should appear, and separators can be included using the separator property to visually group menu items. This flexibility allows for a tailored user interface that meets specific application needs efficiently. Nested menu items are defined within the items property of a parent menu item.

To Display custom menu alone

To display the custom context menu items alone, set the showCustomMenuOnly property to true.

Context menu click

Upon clicking custom menu items, actions are handled using the contextMenuClick event in the diagram. This event allows you to define actions based on which menu item is clicked. For instance, in the example below, the cloning of nodes and the change of fill color for nodes and annotations are efficiently managed and implemented through this event.

<template>
    <div id="app">
        <ejs-diagram id="diagram" ref="diagram" :width='width' :height='height' :nodes='nodes' 
            :contextMenuSettings='contextMenuSettings' :contextMenuClick="contextMenuClick"></ejs-diagram>
    </div>
</template>
<script setup>
import { provide, ref } from "vue";
import { DiagramComponent as EjsDiagram, DiagramContextMenu } from '@syncfusion/ej2-vue-diagrams';

const diagram = ref(null);
const nodes = [{
    id: 'node1',
    width: 100,
    height: 100,
    offsetX: 100,
    offsetY: 100,
    annotations: [{
        id: 'label1',
        content: 'Rectangle1',
    }]
},
{
    id: 'node2',
    width: 100,
    height: 100,
    offsetX: 300,
    offsetY: 100,
    annotations: [{
        id: 'label2',
        content: 'Rectangle2',
    }]
}
];


const width = "100%";
const height = "350px";
const contextMenuSettings= {
        //Enables the context menu
        show: true,
        items: [
          {
            // Text to be displayed
            text: "Fill",
            items: [
              { id: "red", text: "Red" },
              { id: "yellow", text: "Yellow" },
              { id: "green", text: "Green" },
              { id: "blue", text: "Blue" },
            ],
            //Sets the id for the item
            id: "fill",
            target: ".e-elementcontent",
            // Sets the css icons for the item
            iconCss: "e-icons e-paint-bucket",
          },
          {
            text: "Annotation color",
            id: "annotationColor",
            items: [
              { id: "pink", text: "Pink" },
              { id: "orange", text: "Orange" },
              { id: "violet", text: "Violet" },
              { id: "brown", text: "Brown" },
            ],
            target: ".e-elementcontent",
            iconCss: "e-icons e-font-color",
          },
          {
            text: "Clone",
            id: "clone",
            target: ".e-elementcontent",
            iconCss: "e-icons e-copy",
          },
        ],
        // Hides the default context menu items
        showCustomMenuOnly: true,
};

const contextMenuClick = (args) => {
    var diagram = diagram.value.ej2Instances;
    let selectedNode = diagram.selectedItems.nodes[0];
    if (
        selectedNode &&
        args.item.id !== "fill" &&
        args.item.id !== "annotationColor"
    ) {
        if (
        args.item.text === "Red" ||
        args.item.text === "Blue" ||
        args.item.text === "Yellow" ||
        args.item.text === "Green"
        ) {
        selectedNode.style.fill = args.item.text;
        diagram.dataBind();
        } else if (
        args.item.text === "Pink" ||
        args.item.text === "Violet" ||
        args.item.text === "Orange" ||
        args.item.text === "Brown"
        ) {
        selectedNode.annotations[0].style.fill = args.item.text;
        diagram.dataBind();
        } else {
        diagram.copy();
        diagram.paste();
        }
    }
}

provide('diagram', [DiagramContextMenu]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/fabric.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-icons/styles/material.css';
</style>
<template>
  <div id="app">
    <ejs-diagram
      id="diagram"
      ref="diagram"
      :width="width"
      :height="height"
      :nodes="nodes"
      :contextMenuSettings="contextMenuSettings"
      :contextMenuClick="contextMenuClick"
    ></ejs-diagram>
  </div>
</template>
<script>
import {DiagramComponent,DiagramContextMenu} from "@syncfusion/ej2-vue-diagrams";

let nodes = [
  {
    id: "node1",
    width: 100,
    height: 100,
    offsetX: 100,
    offsetY: 100,
    annotations: [
      {
        id: "label1",
        content: "Rectangle1",
      },
    ],
  },
  {
    id: "node2",
    width: 100,
    height: 100,
    offsetX: 300,
    offsetY: 100,
    annotations: [
      {
        id: "label2",
        content: "Rectangle2",
      },
    ],
  },
];


export default {
  name: "App",
  components: {
    "ejs-diagram": DiagramComponent,
  },
  data() {
    return {
      width: "100%",
      height: "350px",
      nodes: nodes,
      contextMenuSettings: {
        //Enables the context menu
        show: true,
        items: [
          {
            // Text to be displayed
            text: "Fill",
            items: [
              { id: "red", text: "Red" },
              { id: "yellow", text: "Yellow" },
              { id: "green", text: "Green" },
              { id: "blue", text: "Blue" },
            ],
            //Sets the id for the item
            id: "fill",
            target: ".e-elementcontent",
            // Sets the css icons for the item
            iconCss: "e-icons e-paint-bucket",
          },
          {
            text: "Annotation color",
            id: "annotationColor",
            items: [
              { id: "pink", text: "Pink" },
              { id: "orange", text: "Orange" },
              { id: "violet", text: "Violet" },
              { id: "brown", text: "Brown" },
            ],
            target: ".e-elementcontent",
            iconCss: "e-icons e-font-color",
          },
          {
            text: "Clone",
            id: "clone",
            target: ".e-elementcontent",
            iconCss: "e-icons e-copy",
          },
        ],
        // Hides the default context menu items
        showCustomMenuOnly: true,
      },
      contextMenuClick: (args) => {
        var diagram = this.$refs.diagram.ej2Instances;
        let selectedNode = diagram.selectedItems.nodes[0];
        if (
          selectedNode &&
          args.item.id !== "fill" &&
          args.item.id !== "annotationColor"
        ) {
          if (
            args.item.text === "Red" ||
            args.item.text === "Blue" ||
            args.item.text === "Yellow" ||
            args.item.text === "Green"
          ) {
            selectedNode.style.fill = args.item.text;
            diagram.dataBind();
          } else if (
            args.item.text === "Pink" ||
            args.item.text === "Violet" ||
            args.item.text === "Orange" ||
            args.item.text === "Brown"
          ) {
            selectedNode.annotations[0].style.fill = args.item.text;
            diagram.dataBind();
          } else {
            diagram.copy();
            diagram.paste();
          }
        }
      },
    };
  },
  provide: {
    diagram: [DiagramContextMenu],
  },
};
</script>
<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
</style>

Context menu open

In certain situations, you may want to hide specific menu items based on the selected elements in the diagram. This can be achieved using the contextMenuOpen event. When the context menu is opened via right-click, the contextMenuOpen event is triggered. Within this event, you can create an array of menu items to hide for the selected element and pass it to the hiddenItems property of the contextMenuOpen event argument. The following example demonstrates how to display different custom menu items for nodes, connectors, and the diagram based on the selection.

<template>
    <div id="app">
        <ejs-diagram id="diagram" ref="diagram" :width='width' :height='height' :nodes='nodes' :connectors='connectors'
            :contextMenuSettings='contextMenuSettings' :contextMenuOpen="contextMenuOpen"
            :contextMenuClick="contextMenuClick"></ejs-diagram>
    </div>
</template>
<script setup>
import { provide, ref } from "vue";
import { DiagramComponent as EjsDiagram, DiagramContextMenu } from '@syncfusion/ej2-vue-diagrams';

const diagram = ref(null);
const nodes = [{
    id: 'node1',
    width: 100,
    height: 100,
    offsetX: 100,
    offsetY: 100,
    annotations: [{
        id: 'label1',
        content: 'Rectangle1',
    }]
},
{
    id: 'node2',
    width: 100,
    height: 100,
    offsetX: 300,
    offsetY: 100,
    annotations: [{
        id: 'label2',
        content: 'Rectangle2',
    }]
}
];
const connectors = [{
    id: 'connector1',
    sourceID: 'node1',
    targetID: 'node2',
    type: 'Straight',
}]

const width = "100%";
const height = "350px";
const contextMenuSettings = {
    show: true,
    items: [
        {
        text: "Change fill",
        id: "applyFill",
        target: ".e-diagramcontent",
        iconCss: "e-icons e-paint-bucket",
        },
        {
        text: "Change stroke",
        id: "applyStroke",
        target: ".e-diagramcontent",
        iconCss: "e-icons e-edit",
        },
        {
        text: "Select All",
        id: "selectAll",
        target: ".e-diagramcontent",
        },
    ],
    showCustomMenuOnly: true,
};
const contextMenuOpen = (args) => {
    var diagram = diagram.value.ej2Instances;
    let hiddenItems = [];
    let selectedNode = diagram.selectedItems.nodes[0];
    let selectedConnector = diagram.selectedItems.connectors[0];
    if (selectedNode || selectedConnector) {
        hiddenItems.push("selectAll");
    } else {
        hiddenItems = ["applyFill", "applyStroke"];
    }
    args.hiddenItems = hiddenItems;
}
const contextMenuClick = (args) => {
    var diagram = diagram.value.ej2Instances;
    let selectedNode = diagram.selectedItems.nodes[0];
    let selectedConnector = diagram.selectedItems.connectors[0];
    if (selectedNode || selectedConnector) {
        if (selectedNode) {
        if (args.item.id === "applyFill") {
            selectedNode.style.fill =
            selectedNode.style.fill === "#6BA5D7" ? "green" : "#6BA5D7";
        } else if (args.item.id === "applyStroke") {
            selectedNode.style.strokeColor =
            selectedNode.style.strokeColor === "black" ? "yellow" : "black";
        }
        }
        if (selectedConnector) {
        if (args.item.id === "applyFill") {
            selectedConnector.targetDecorator.style.fill =
            selectedConnector.targetDecorator.style.fill === "yellow"? "black": "yellow";
        }
        selectedConnector.style.strokeColor = selectedConnector.style.strokeColor === "black"? "yellow": "black";
        }
    } else {
        diagram.selectAll();
    }
}

provide('diagram', [DiagramContextMenu]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/fabric.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-icons/styles/material.css';
</style>
<template>
  <div id="app">
    <ejs-diagram
      id="diagram"
      ref="diagram"
      :width="width"
      :height="height"
      :nodes="nodes"
      :connectors="connectors"
      :contextMenuSettings="contextMenuSettings"
      :contextMenuOpen="contextMenuOpen"
      :contextMenuClick="contextMenuClick"
    ></ejs-diagram>
  </div>
</template>
<script>
import {DiagramComponent,DiagramContextMenu} from "@syncfusion/ej2-vue-diagrams";

let nodes = [
  {
    id: "node1",
    width: 100,
    height: 100,
    offsetX: 100,
    offsetY: 100,
    annotations: [
      {
        id: "label1",
        content: "Rectangle1",
      },
    ],
  },
  {
    id: "node2",
    width: 100,
    height: 100,
    offsetX: 300,
    offsetY: 100,
    annotations: [
      {
        id: "label2",
        content: "Rectangle2",
      },
    ],
  },
];

let connectors = [
  {
    id: "connector1",
    sourceID: "node1",
    targetID: "node2",
    type: "Straight",
  },
];

export default {
  name: "App",
  components: {
    "ejs-diagram": DiagramComponent,
  },
  data() {
    return {
      width: "100%",
      height: "350px",
      nodes: nodes,
      connectors: connectors,
      contextMenuSettings: {
        show: true,
        items: [
          {
            text: "Change fill",
            id: "applyFill",
            target: ".e-diagramcontent",
            iconCss: "e-icons e-paint-bucket",
          },
          {
            text: "Change stroke",
            id: "applyStroke",
            target: ".e-diagramcontent",
            iconCss: "e-icons e-edit",
          },
          {
            text: "Select All",
            id: "selectAll",
            target: ".e-diagramcontent",
          },
        ],
        showCustomMenuOnly: true,
      },
      contextMenuOpen: (args) => {
        var diagram = this.$refs.diagram.ej2Instances;
        let hiddenItems = [];
        let selectedNode = diagram.selectedItems.nodes[0];
        let selectedConnector = diagram.selectedItems.connectors[0];
        if (selectedNode || selectedConnector) {
          hiddenItems.push("selectAll");
        } else {
          hiddenItems = ["applyFill", "applyStroke"];
        }
        args.hiddenItems = hiddenItems;
      },
      contextMenuClick: (args) => {
        var diagram = this.$refs.diagram.ej2Instances;
        let selectedNode = diagram.selectedItems.nodes[0];
        let selectedConnector = diagram.selectedItems.connectors[0];
        if (selectedNode || selectedConnector) {
          if (selectedNode) {
            if (args.item.id === "applyFill") {
              selectedNode.style.fill =
                selectedNode.style.fill === "#6BA5D7" ? "green" : "#6BA5D7";
            } else if (args.item.id === "applyStroke") {
              selectedNode.style.strokeColor =
                selectedNode.style.strokeColor === "black" ? "yellow" : "black";
            }
          }
          if (selectedConnector) {
            if (args.item.id === "applyFill") {
              selectedConnector.targetDecorator.style.fill =
                selectedConnector.targetDecorator.style.fill === "yellow"
                  ? "black"
                  : "yellow";
            }
            selectedConnector.style.strokeColor =
              selectedConnector.style.strokeColor === "black"
                ? "yellow"
                : "black";
          }
        } else {
          diagram.selectAll();
        }
      },
    };
  },
  provide: {
    diagram: [DiagramContextMenu],
  },
};
</script>
<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
</style>

Context menu with Url

url property of the menu item is used to set the url of any website which will be opened upon clicking on them. The following example shows the context menu with url for three websites.

<template>
    <div id="app">
        <ejs-diagram id="diagram" ref="diagram" :width='width' :height='height' :nodes='nodes' :connectors='connectors'
            :contextMenuSettings='contextMenuSettings'></ejs-diagram>
    </div>
</template>
<script setup>
import { provide, ref } from "vue";
import { DiagramComponent as EjsDiagram, DiagramContextMenu } from '@syncfusion/ej2-vue-diagrams';

const diagram = ref(null);
const nodes = [{
    id: 'node1',
    width: 100,
    height: 100,
    offsetX: 100,
    offsetY: 100,
    annotations: [{
        id: 'label1',
        content: 'Rectangle1',
    }]
},
{
    id: 'node2',
    width: 100,
    height: 100,
    offsetX: 300,
    offsetY: 100,
    annotations: [{
        id: 'label2',
        content: 'Rectangle2',
    }]
}
];
const connectors = [{
    id: 'connector1',
    sourceID: 'node1',
    targetID: 'node2',
    type: 'Straight',
}]

const width = "100%";
const height = "350px";
const contextMenuSettings = {
   show: true,
        items: [
          {
            text: "Google.com",
            id: "google",
            target: ".e-diagramcontent",
            url: "https://www.google.co.in/",
          },
          {
            text: "w3schools.com",
            id: "W3Schools",
            target: ".e-diagramcontent",
            url: "https://www.w3schools.com/",
          },
          {
            text: "stackoverflow.com",
            id: "stackoverflow",
            target: ".e-diagramcontent",
            url: "https://stackoverflow.com/",
          },
        ],
        showCustomMenuOnly: true,
};


provide('diagram', [DiagramContextMenu]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/fabric.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-icons/styles/material.css';
</style>
<template>
  <div id="app">
    <ejs-diagram
      id="diagram"
      ref="diagram"
      :width="width"
      :height="height"
      :nodes="nodes"
      :contextMenuSettings="contextMenuSettings"
    ></ejs-diagram>
  </div>
</template>
<script>
import {
  DiagramComponent,
  DiagramContextMenu,
} from "@syncfusion/ej2-vue-diagrams";

let nodes = [
  {
    id: "node1",
    width: 100,
    height: 100,
    offsetX: 100,
    offsetY: 100,
    annotations: [
      {
        id: "label1",
        content: "Rectangle1",
      },
    ],
  },
  {
    id: "node2",
    width: 100,
    height: 100,
    offsetX: 300,
    offsetY: 100,
    annotations: [
      {
        id: "label2",
        content: "Rectangle2",
      },
    ],
  },
];


export default {
  name: "App",
  components: {
    "ejs-diagram": DiagramComponent,
  },
  data() {
    return {
      width: "100%",
      height: "350px",
      nodes: nodes,
      contextMenuSettings: {
        show: true,
        items: [
          {
            text: "Google.com",
            id: "google",
            target: ".e-diagramcontent",
            url: "https://www.google.co.in/",
          },
          {
            text: "w3schools.com",
            id: "W3Schools",
            target: ".e-diagramcontent",
            url: "https://www.w3schools.com/",
          },
          {
            text: "stackoverflow.com",
            id: "stackoverflow",
            target: ".e-diagramcontent",
            url: "https://stackoverflow.com/",
          },
        ],
        showCustomMenuOnly: true,
      },
    };
  },
  provide: {
    diagram: [DiagramContextMenu],
  },
};
</script>
<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
</style>

Template Support for Context menu

Diagram provides template support for the context menu. The template for the context menu items can be customized before rendering by using the contextMenuBeforeItemRender event, which triggers while rendering each menu item.

In the following example, menu items are rendered with shortcut key codes for specific actions in the context menu using a template. The key codes for cut, copy, and paste actions are displayed at the right corner of the menu items by adding a span element in the contextMenuBeforeItemRender event.

<template>
    <div id="app">
        <ejs-diagram id="diagram"  ref="diagram" :width='width' :height='height' :nodes='nodes'
            :contextMenuSettings='contextMenuSettings'  :contextMenuClick='contextMenuClick'
      :contextMenuBeforeItemRender='contextMenuBeforeItemRender'></ejs-diagram>
    </div>
</template>
<script setup>
import { provide } from "vue";
import { DiagramComponent as EjsDiagram, DiagramContextMenu } from '@syncfusion/ej2-vue-diagrams';
import { createElement } from "@syncfusion/ej2-base";

const nodes = [{
    id: 'node1',
    width: 100,
    height: 100,
    offsetX: 100,
    offsetY: 100,
    annotations: [{
        id: 'label1',
        content: 'Rectangle1',
    }]
},
{
    id: 'node2',
    width: 100,
    height: 100,
    offsetX: 300,
    offsetY: 100,
    annotations: [{
        id: 'label2',
        content: 'Rectangle2',
    }]
}
];


const width = "100%";
const height = "350px";
const contextMenuSettings = {
     show: true,
        items: [
          {
            text: "Cut",
            id: "Cut",
            target: ".e-diagramcontent",
            iconCss: "e-cut e-icons",
          },
          {
            text: "Copy",
            id: "Copy",
            target: ".e-diagramcontent",
            iconCss: "e-icons e-copy",
          },
          {
            text: "Paste",
            id: "Paste",
            target: ".e-diagramcontent",
            iconCss: "e-icons e-paste",
          },
        ],
        showCustomMenuOnly: true,
};
const contextMenuBeforeItemRender = (args) => {
        // To render template in li.
        let shortCutSpan = createElement("span");
        let text = args.item.text;
        let shortCutText =
          text === "Cut"
            ? " Ctrl + X"
            : text === "Copy"
            ? " Ctrl + C"
            : " Ctrl + V";
        shortCutSpan.textContent = shortCutText;
        shortCutSpan.setAttribute("class", "shortcut");
        args.element.appendChild(shortCutSpan);
};
const contextMenuClick = (args) => {
        var diagram = diagram.value.ej2Instances;
        let selectedNode = diagram.selectedItems.nodes[0];
        if (selectedNode) {
          if (args.item.text === "Cut") {
            diagram.cut();
          } else if (args.item.text === "Copy") {
            diagram.copy();
          }
        }
        if (args.item.text === "Paste") {
          diagram.paste();
        }
};

provide('diagram', [DiagramContextMenu]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/fabric.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-icons/styles/material.css';
</style>
<template>
  <div id="app">
    <ejs-diagram
      id="diagram"
      ref="diagram"
      :width="width"
      :height="height"
      :nodes="nodes"
      :contextMenuSettings="contextMenuSettings"
      :contextMenuClick="contextMenuClick"
      :contextMenuBeforeItemRender="contextMenuBeforeItemRender"
    ></ejs-diagram>
  </div>
</template>
<script>
import {DiagramComponent, DiagramContextMenu,} from "@syncfusion/ej2-vue-diagrams";
import { createElement } from "@syncfusion/ej2-base";

let nodes = [
  {
    id: "node1",
    width: 100,
    height: 100,
    offsetX: 100,
    offsetY: 100,
    annotations: [
      {
        id: "label1",
        content: "Rectangle1",
      },
    ],
  },
  {
    id: "node2",
    width: 100,
    height: 100,
    offsetX: 300,
    offsetY: 100,
    annotations: [
      {
        id: "label2",
        content: "Rectangle2",
      },
    ],
  },
];

export default {
  name: "App",
  components: {
    "ejs-diagram": DiagramComponent,
  },
  data() {
    return {
      width: "100%",
      height: "350px",
      nodes: nodes,
      contextMenuSettings: {
        show: true,
        items: [
          {
            text: "Cut",
            id: "Cut",
            target: ".e-diagramcontent",
            iconCss: "e-cut e-icons",
          },
          {
            text: "Copy",
            id: "Copy",
            target: ".e-diagramcontent",
            iconCss: "e-icons e-copy",
          },
          {
            text: "Paste",
            id: "Paste",
            target: ".e-diagramcontent",
            iconCss: "e-icons e-paste",
          },
        ],
        showCustomMenuOnly: true,
      },
      contextMenuBeforeItemRender: (args) => {
        // To render template in li.
        let shortCutSpan = createElement("span");
        let text = args.item.text;
        let shortCutText =
          text === "Cut"
            ? " Ctrl + X"
            : text === "Copy"
            ? " Ctrl + C"
            : " Ctrl + V";
        shortCutSpan.textContent = shortCutText;
        shortCutSpan.setAttribute("class", "shortcut");
        args.element.appendChild(shortCutSpan);
      },
      contextMenuClick: (args) => {
        var diagram = this.$refs.diagram.ej2Instances;
        let selectedNode = diagram.selectedItems.nodes[0];
        if (selectedNode) {
          if (args.item.text === "Cut") {
            diagram.cut();
          } else if (args.item.text === "Copy") {
            diagram.copy();
          }
        }
        if (args.item.text === "Paste") {
          diagram.paste();
        }
      },
    };
  },
  provide: {
    diagram: [DiagramContextMenu],
  },
};
</script>
<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
</style>

Context menu events

Event Description
contextMenuBeforeItemRender Triggers while initializing each menu item.
contextMenuOpen Triggers upon right-click before opening the context menu.
contextMenuClick Triggers when a menu item is clicked.

The following example shows how to get these events.

<template>
  <div id="app">
    <ejs-diagram
      id="diagram"
      :width="width"
      :height="height"
      :nodes="nodes"
      :connectors="connectors"
      :contextMenuSettings="contextMenuSettings"
      :contextMenuOpen="contextMenuOpen"
      :contextMenuBeforeItemRender="contextMenuBeforeItemRender"
      :contextMenuClick="contextMenuClick"
    ></ejs-diagram>
  </div>
</template>
<script setup>
import { provide } from "vue";
import {DiagramComponent as EjsDiagram,DiagramContextMenu,Diagram} from "@syncfusion/ej2-vue-diagrams";

let nodes = [
  {
    id: "node1",
    width: 100,
    height: 100,
    offsetX: 100,
    offsetY: 100,
    annotations: [
      {
        id: "label1",
        content: "Rectangle1",
      },
    ],
  },
  {
    id: "node2",
    width: 100,
    height: 100,
    offsetX: 300,
    offsetY: 100,
    annotations: [
      {
        id: "label2",
        content: "Rectangle2",
      },
    ],
  },
];
let connectors = [
  {
    id: "connector1",
    sourceID: "node1",
    targetID: "node2",
    type: "Straight",
  },
];

const width = "100%";
const height = "350px";
const contextMenuSettings = {
  show: true,
  items: [
          {
            text: "menu item 1",
            id: "item1",
          },
          {
            text: "menu item 2",
            id: "item2",
          },
        ],
        showCustomMenuOnly: true,
};
const contextMenuBeforeItemRender = (args) => {
  //Triggers for each menu item
  console.log("context menu before item render");
};
const contextMenuOpen = (args) => {
  //Triggers when the menu is openned
  console.log("context menu openned");
};
const contextMenuClick = (args) => {
  //Triggers when the item is clicked
  console.log("context menu clicked");
};

provide("diagram", [DiagramContextMenu]);
</script>
<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/fabric.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-icons/styles/material.css';
</style>
<template>
  <div id="app">
    <ejs-diagram
      id="diagram"
      :width="width"
      :height="height"
      :nodes="nodes"
      :connectors="connectors"
      :contextMenuSettings="contextMenuSettings"
      :contextMenuOpen="contextMenuOpen"
      :contextMenuBeforeItemRender="contextMenuBeforeItemRender"
      :contextMenuClick="contextMenuClick"
    ></ejs-diagram>
  </div>
</template>
<script>
import {DiagramComponent,DiagramContextMenu,Diagram} from "@syncfusion/ej2-vue-diagrams";

let nodes = [
  {
    id: "node1",
    width: 100,
    height: 100,
    offsetX: 100,
    offsetY: 100,
    annotations: [
      {
        id: "label1",
        content: "Rectangle1",
      },
    ],
  },
  {
    id: "node2",
    width: 100,
    height: 100,
    offsetX: 300,
    offsetY: 100,
    annotations: [
      {
        id: "label2",
        content: "Rectangle2",
      },
    ],
  },
];

let connectors = [
  {
    id: "connector1",
    sourceID: "node1",
    targetID: "node2",
    type: "Straight",
  },
];

export default {
  name: "App",
  components: {
    "ejs-diagram": DiagramComponent,
  },
  data() {
    return {
      width: "100%",
      height: "350px",
      nodes: nodes,
      connectors: connectors,
      contextMenuSettings: {
        show: true,
        items: [
          {
            text: "menu item 1",
            id: "item1",
          },
          {
            text: "menu item 2",
            id: "item2",
          },
        ],
        showCustomMenuOnly: true,
      },
      contextMenuBeforeItemRender:function (args) {
        //Triggers for each menu item
        console.log("context menu before item render");
      },
      contextMenuOpen: function (args) {
        //Triggers when the menu is openned
        console.log("context menu openned");
      },
      contextMenuClick: function (args) {
        //Triggers when the item is clicked
        console.log("context menu clicked");
      },
    };
  },
  provide: {
    diagram: [DiagramContextMenu],
  },
};
</script>
<style>
@import "../node_modules/@syncfusion/ej2-vue-diagrams/styles/material.css";
</style>