Process the tree node operations using context menu in Vue Treeview component
23 Dec 202424 minutes to read
You can integrate a context menu with the TreeView component to perform tree-view-related operations such as adding, removing, and renaming nodes. The following example demonstrates how to use the select event of the context menu to manipulate TreeView operations.
<template>
<div id="app">
<div class="control_wrapper">
<ejs-treeview id='treeview' :fields="fields" :nodeClicked='nodeclicked'>
<ejs-contextmenu id='contentmenutree' target='#treeview' :items='menuItems' :beforeOpen='beforeopen'
:select='menuclick'></ejs-contextmenu>
</ejs-treeview>
</div>
</div>
</template>
<script setup>
import { TreeViewComponent as EjsTreeview, ContextMenuComponent as EjsContextmenu } from "@syncfusion/ej2-vue-navigations";
var dataSource = [
{
id: '01', name: 'Local Disk (C:)', expanded: true, hasAttribute: { class: 'remove rename' },
subChild: [
{
id: '01-01', name: 'Program Files',
subChild: [
{ id: '01-01-01', name: 'Windows NT' },
{ id: '01-01-02', name: 'Windows Mail' },
{ id: '01-01-03', name: 'Windows Photo Viewer' },
]
},
{
id: '01-02', name: 'Users', expanded: true,
subChild: [
{ id: '01-02-01', name: 'Smith' },
{ id: '01-02-02', name: 'Public' },
{ id: '01-02-03', name: 'Admin' },
]
},
{
id: '01-03', name: 'Windows',
subChild: [
{ id: '01-03-01', name: 'Boot' },
{ id: '01-03-02', name: 'FileManager' },
{ id: '01-03-03', name: 'System32' },
]
},
]
},
{
id: '02', name: 'Local Disk (D:)', hasAttribute: { class: 'rename' },
subChild: [
{
id: '02-01', name: 'Personals',
subChild: [
{ id: '02-01-01', name: 'My photo.png' },
{ id: '02-01-02', name: 'Rental document.docx' },
{ id: '02-01-03', name: 'Pay slip.pdf' },
]
},
{
id: '02-02', name: 'Projects',
subChild: [
{ id: '02-02-01', name: 'ASP Application' },
{ id: '02-02-02', name: 'TypeScript Application' },
{ id: '02-02-03', name: 'React Application' },
]
},
{
id: '02-03', name: 'Office',
subChild: [
{ id: '02-03-01', name: 'Work details.docx' },
{ id: '02-03-02', name: 'Weekly report.docx' },
{ id: '02-03-03', name: 'Wish list.csv' },
]
},
]
},
{
id: '03', name: 'Local Disk (E:)', icon: 'folder', hasAttribute: { class: 'remove' },
subChild: [
{
id: '03-01', name: 'Pictures',
subChild: [
{ id: '03-01-01', name: 'Wind.jpg' },
{ id: '03-01-02', name: 'Stone.jpg' },
{ id: '03-01-03', name: 'Home.jpg' },
]
},
{
id: '03-02', name: 'Documents',
subChild: [
{ id: '03-02-01', name: 'Environment Pollution.docx' },
{ id: '03-02-02', name: 'Global Warming.ppt' },
{ id: '03-02-03', name: 'Social Network.pdf' },
]
},
{
id: '03-03', name: 'Study Materials',
subChild: [
{ id: '03-03-01', name: 'UI-Guide.pdf' },
{ id: '03-03-02', name: 'Tutorials.zip' },
{ id: '03-03-03', name: 'TypeScript.7z' },
]
},
]
}
];
const fields = { dataSource: dataSource, id: 'id', text: 'name', child: 'subChild', htmlAttributes: 'hasAttribute' };
const menuItems = [
{ text: 'Add New Item' },
{ text: 'Rename Item' },
{ text: 'Remove Item' }
];
let index = 1;
const nodeclicked = (args) => {
if (args.event.which === 3) {
var treeObj = document.getElementById('treeview').ej2_instances[0];
treeObj.selectedNodes = [args.node.getAttribute('data-uid')];
}
};
const menuclick = (args) => {
var treevalidate = document.getElementById('treeview').ej2_instances[0];
var targetNodeId = treevalidate.selectedNodes[0];
if (args.item.text == "Add New Item") {
var nodeId = "tree_" + index;
var item = { id: nodeId, name: "New Folder" };
treevalidate.addNodes([item], targetNodeId, null);
index++;
treevalidate.fields.dataSource.push(item);
treevalidate.beginEdit(nodeId);
}
else if (args.item.text == "Remove Item") {
treevalidate.removeNodes([targetNodeId]);
}
else if (args.item.text == "Rename Item") {
treevalidate.beginEdit(targetNodeId);
}
};
const beforeopen = () => {
var treevalidate = document.getElementById('treeview').ej2_instances[0];
var targetNodeId = treevalidate.selectedNodes[0];
var targetNode = document.querySelector('[data-uid="' + targetNodeId + '"]');
var contentmenutree = document.getElementById('contentmenutree').ej2_instances[0];
if (targetNode.classList.contains('remove')) {
contentmenutree.enableItems(['Remove Item'], false);
}
else {
contentmenutree.enableItems(['Remove Item'], true);
}
if (targetNode.classList.contains('rename')) {
contentmenutree.enableItems(['Rename Item'], false);
}
else {
contentmenutree.enableItems(['Rename Item'], true);
}
};
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/material.css";
.control_wrapper {
display: block;
max-width: 400px;
max-height: 320px;
margin: auto;
overflow: auto;
border: 1px solid #dddddd;
border-radius: 3px;
}
#app {
width: 350px;
margin: 0 auto;
}
#contentmenutree {
padding: 0px;
font-size: inherit;
}
</style>
<template>
<div id="app">
<div class="control_wrapper">
<ejs-treeview id='treeview' :fields="fields" :nodeClicked='nodeclicked'>
<ejs-contextmenu id='contentmenutree' target='#treeview' :items='menuItems' :beforeOpen='beforeopen'
:select='menuclick'></ejs-contextmenu>
</ejs-treeview>
</div>
</div>
</template>
<script>
import { TreeViewComponent, ContextMenuComponent } from "@syncfusion/ej2-vue-navigations";
export default {
name: "App",
components: {
"ejs-treeview": TreeViewComponent,
"ejs-contextmenu": ContextMenuComponent
},
data() {
var dataSource = [
{
id: '01', name: 'Local Disk (C:)', expanded: true, hasAttribute: { class: 'remove rename' },
subChild: [
{
id: '01-01', name: 'Program Files',
subChild: [
{ id: '01-01-01', name: 'Windows NT' },
{ id: '01-01-02', name: 'Windows Mail' },
{ id: '01-01-03', name: 'Windows Photo Viewer' },
]
},
{
id: '01-02', name: 'Users', expanded: true,
subChild: [
{ id: '01-02-01', name: 'Smith' },
{ id: '01-02-02', name: 'Public' },
{ id: '01-02-03', name: 'Admin' },
]
},
{
id: '01-03', name: 'Windows',
subChild: [
{ id: '01-03-01', name: 'Boot' },
{ id: '01-03-02', name: 'FileManager' },
{ id: '01-03-03', name: 'System32' },
]
},
]
},
{
id: '02', name: 'Local Disk (D:)', hasAttribute: { class: 'rename' },
subChild: [
{
id: '02-01', name: 'Personals',
subChild: [
{ id: '02-01-01', name: 'My photo.png' },
{ id: '02-01-02', name: 'Rental document.docx' },
{ id: '02-01-03', name: 'Pay slip.pdf' },
]
},
{
id: '02-02', name: 'Projects',
subChild: [
{ id: '02-02-01', name: 'ASP Application' },
{ id: '02-02-02', name: 'TypeScript Application' },
{ id: '02-02-03', name: 'React Application' },
]
},
{
id: '02-03', name: 'Office',
subChild: [
{ id: '02-03-01', name: 'Work details.docx' },
{ id: '02-03-02', name: 'Weekly report.docx' },
{ id: '02-03-03', name: 'Wish list.csv' },
]
},
]
},
{
id: '03', name: 'Local Disk (E:)', icon: 'folder', hasAttribute: { class: 'remove' },
subChild: [
{
id: '03-01', name: 'Pictures',
subChild: [
{ id: '03-01-01', name: 'Wind.jpg' },
{ id: '03-01-02', name: 'Stone.jpg' },
{ id: '03-01-03', name: 'Home.jpg' },
]
},
{
id: '03-02', name: 'Documents',
subChild: [
{ id: '03-02-01', name: 'Environment Pollution.docx' },
{ id: '03-02-02', name: 'Global Warming.ppt' },
{ id: '03-02-03', name: 'Social Network.pdf' },
]
},
{
id: '03-03', name: 'Study Materials',
subChild: [
{ id: '03-03-01', name: 'UI-Guide.pdf' },
{ id: '03-03-02', name: 'Tutorials.zip' },
{ id: '03-03-03', name: 'TypeScript.7z' },
]
},
]
}
];
return {
fields: { dataSource: dataSource, id: 'id', text: 'name', child: 'subChild', htmlAttributes: 'hasAttribute' },
menuItems: [
{ text: 'Add New Item' },
{ text: 'Rename Item' },
{ text: 'Remove Item' }
],
index: 1,
}
},
methods: {
nodeclicked: function (args) {
if (args.event.which === 3) {
var treeObj = document.getElementById('treeview').ej2_instances[0];
treeObj.selectedNodes = [args.node.getAttribute('data-uid')];
}
},
menuclick: function (args) {
var treevalidate = document.getElementById('treeview').ej2_instances[0];
var targetNodeId = treevalidate.selectedNodes[0];
if (args.item.text == "Add New Item") {
var nodeId = "tree_" + this.index;
var item = { id: nodeId, name: "New Folder" };
treevalidate.addNodes([item], targetNodeId, null);
this.index++;
treevalidate.fields.dataSource.push(item);
treevalidate.beginEdit(nodeId);
}
else if (args.item.text == "Remove Item") {
treevalidate.removeNodes([targetNodeId]);
}
else if (args.item.text == "Rename Item") {
treevalidate.beginEdit(targetNodeId);
}
},
beforeopen: function (args) {
var treevalidate = document.getElementById('treeview').ej2_instances[0];
var targetNodeId = treevalidate.selectedNodes[0];
var targetNode = document.querySelector('[data-uid="' + targetNodeId + '"]');
var contentmenutree = document.getElementById('contentmenutree').ej2_instances[0];
if (targetNode.classList.contains('remove')) {
contentmenutree.enableItems(['Remove Item'], false);
}
else {
contentmenutree.enableItems(['Remove Item'], true);
}
if (targetNode.classList.contains('rename')) {
contentmenutree.enableItems(['Rename Item'], false);
}
else {
contentmenutree.enableItems(['Rename Item'], true);
}
}
}
}
</script>
<style>
@import "../node_modules/@syncfusion/ej2-base/styles/material.css";
@import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/material.css";
.control_wrapper {
display: block;
max-width: 400px;
max-height: 320px;
margin: auto;
overflow: auto;
border: 1px solid #dddddd;
border-radius: 3px;
}
#app {
width: 350px;
margin: 0 auto;
}
#contentmenutree {
padding: 0px;
font-size: inherit;
}
</style>