antonyboom antonyboom - 4 months ago 98
AngularJS Question

Custom Contexmenu for different node in jstree angular directive

In my project I have tree based on jstee angular directive. I build this tree with help 2 api requests. This requests provide data for folder and end point child node (filters). Also I created custom context menu, with some functions for different types of node. In this context menu I defined variable

check
and with help this variable I set restrictions for operations with node. The full code of context menu looks like:

$scope.contextMenu = {
"create": {
"label": "Create Folder",
"icon": "ico/folder.png",
"action": function (data) {
var inst = $.jstree.reference(data.reference),
obj = inst.get_node(data.reference),
id = obj['original']['id'];
var check = obj['original']['folderId'];

if (typeof check == "undefined") {
obj = {
text: prompt("put folder name"),
parent: id
};
eventService.createFolder(obj);
setTimeout(function () {
getTreeData();
$scope.load();
}, 100);
}
else {
alert("This function is not available");
return false
}
// inst.refresh(true)
}
},
"rename": {
"label": "Rename Folder",
"icon": "ico/folder.png",
"action": function (data) {
var inst = $.jstree.reference(data.reference),
obj = inst.get_node(data.reference),
check = obj['original']['folderId'];

if (typeof check == "undefined") {
var rename = {
id: obj.id,
text: prompt("put your name")
};
eventService.modifyFolder(rename);
inst.rename_node(obj, rename.text);
}
else {
alert("This function is not available");
return false
}
}
},
"delete": {
"label": "Delete Folder",
"icon": "ico/folder.png",
"action": function (data) {
var inst = $.jstree.reference(data.reference),
obj = inst.get_node(data.reference),
node = inst.get_selected(),
check = obj['original']['folderId'];

if (typeof check == "undefined") {
if (!node.length) {
return false;
}
eventService.deleteFolder(node);
inst.delete_node(node);
}
else {
alert("This function is not available");
return false
}
}
},
"store": {
"label": "Store Filter",
"icon": "ico/file.png",
"action": function (data) {
$scope.saveStateString();
var inst = $.jstree.reference(data.reference),
obj = inst.get_node(data.reference),
id = obj['original']['id'],
check = obj['original']['folderId'];

if (typeof check == "undefined") {
obj = {
body: $scope.state,
folderId: id,
text: prompt("put filter name")
};
// console.log(obj.body);
setTimeout(function () {
eventService.storeFilter(obj);
}, 1000);
setTimeout(function () {
getTreeData();
$scope.load();
alert("click to public filters to refresh the tree")
}, 1500)
} else {
alert("This function is not available");
return false
}
}
},
"remove": {
"label": "Remove Filter",
"icon": "ico/file.png",
"action": function (data) {
var inst = $.jstree.reference(data.reference),
node = inst.get_selected(),
obj = inst.get_node(data.reference),
check = obj['original']['folderId'];

if (typeof check == "undefined") {
alert("This function is not available");
return false
} else {
if (!node.length) {
return false;
}
eventService.deleteFilter(node);
inst.delete_node(node);
}
}
}
};


Now I'm trying to split this context menu by type of node, that for each node I could see different context menu, I found some solutions here and it says:

$('#jstree').jstree({
'contextmenu' : {
'items' : customMenu
},
'plugins' : ['contextmenu', 'types'],
'types' : {
'#' : { /* options */ },
'level_1' : { /* options */ },
'level_2' : { /* options */ }
// etc...
}
});
function customMenu(node)
{
var items = {
'item1' : {
'label' : 'item1',
'action' : function () { /* action */ }
},
'item2' : {
'label' : 'item2',
'action' : function () { /* action */ }
}
}

if (node.type === 'level_1') {
delete items.item2;
} else if (node.type === 'level_2') {
delete items.item1;
}

return items;
}


I was trying to repeat this way in my app but always see "undefined" instead context menu.

Could anybody help me please to resolve my problem? Plunker with my code

Answer

Be sure you are using working jstree directive. I replaced mistakes in your directive

  if (config.plugins.indexOf('contextmenu') >= 0) {
                if (a.treeContextmenu) {
                    config.contextmenu = s[a.treeContextmenu];
                }
            }

            // if (config.plugins.indexOf('contextmenu') >= 0) {
            //     if (a.treeContextmenu) {
            //         config.contextmenu = config.contextmenu || {};
            //
            //         if (a.treeContextmenuaction != undefined) {
            //             config.contextmenu.items = function(e) {
            //                 return s.$eval(a.treeContextmenuaction)(e);
            //             }
            //         } else {
            //             config.contextmenu.items = function() {
            //                 return s[a.treeContextmenu];
            //             }
            //         }
            //     }
            // }

Your code should look like

$scope.contextMenu = {
    "items": function custom (node){

            // your menu
      }

     if(something){
           // do whatever
      }

     return items
 }

This is your working plunker!

Comments