23

I'm using jsTree 3.0.0 and I need to modify the context in one of the following ways:

  • Change label language for the default items, disable some default items and add new items.
  • Rewrite all items and bind to some new items the create, rename and delete function.

I tried several approaches but nothing worked. For example, this returns Uncaught TypeError: Object [object global] has no method 'create' when I click on create.

"contextmenu":{
    "items": function($node) {
        return {
            createItem : {
                 "label" : "Create New Branch",
                 "action" : function(obj) { this.create(obj); alert(obj.text())},
                 "_class" : "class"
            },
            renameItem : {
                 "label" : "Rename Branch",
                 "action" : function(obj) { this.rename(obj);}
            },
            deleteItem : {
                 "label" : "Remove Branch",
                 "action" : function(obj) { this.remove(obj); }
            }
        };
    }
},

If I try to add one item as in the next example, I loose the default menu items:

items : { 
    "create_folder" : {
        "separator_before" : false,
        "separator_after" : false,
        "label" : "Create Folder",
        "action" : function (obj) { alert(1); /* this is the tree, obj is the node */ }
    }
}

Where am I wrong?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
narcolepticvolcano
  • 1,037
  • 1
  • 10
  • 25

6 Answers6

47

Resolved:

"contextmenu":{         
    "items": function($node) {
        var tree = $("#tree").jstree(true);
        return {
            "Create": {
                "separator_before": false,
                "separator_after": false,
                "label": "Create",
                "action": function (obj) { 
                    $node = tree.create_node($node);
                    tree.edit($node);
                }
            },
            "Rename": {
                "separator_before": false,
                "separator_after": false,
                "label": "Rename",
                "action": function (obj) { 
                    tree.edit($node);
                }
            },                         
            "Remove": {
                "separator_before": false,
                "separator_after": false,
                "label": "Remove",
                "action": function (obj) { 
                    tree.delete_node($node);
                }
            }
        };
    }
}
narcolepticvolcano
  • 1,037
  • 1
  • 10
  • 25
  • I want to get my updated `data` at any type of modification done. How could I achieve. ? – Hashir Hussain Oct 29 '15 at 13:44
  • 3
    when using your code , `Uncaught TypeError: tree.create_node is not a function` error occurred for create action – Ahmad Badpey Mar 27 '16 at 09:29
  • 1
    Most likely, you have forgot to change "#tree" to the id of your tree in html in this line: var tree = $("#tree").jstree(true); – Виталий Белоусов Jul 29 '17 at 14:48
  • You can also get the tree instance like this: `var tree = $.jstree.reference(obj.reference);` This is particularly useful when sharing the same contextmenu config accross distinct trees. .. (There may be other ways) – Myobis Apr 18 '19 at 16:15
  • @sara_thepot solution is a working solution. If anyone wants to see complete source code, you can refer [jsTree with custom context menu](https://everyething.com/jsTree-with-Custom-Context-Menu) – Asif Nowaj Nov 02 '19 at 15:42
7

for jstree v3.+ (i test 3.2.1) this example work

"contextmenu":{
                    "items": function () {
                        return {
                            "Create": {
                                "label": "Create",
                                "action": function (data) {
                                    var ref = $.jstree.reference(data.reference);
                                        sel = ref.get_selected();
                                    if(!sel.length) { return false; }
                                    sel = sel[0];
                                    sel = ref.create_node(sel, {"type":"file"});
                                    if(sel) {
                                        ref.edit(sel);
                                    }

                                }
                            },
                            "Rename": {
                                "label": "Rename",
                                "action": function (data) {
                                    var inst = $.jstree.reference(data.reference);
                                        obj = inst.get_node(data.reference);
                                    inst.edit(obj);
                                }
                            },
                            "Delete": {
                                "label": "Delete",
                                "action": function (data) {
                                    var ref = $.jstree.reference(data.reference),
                                        sel = ref.get_selected();
                                    if(!sel.length) { return false; }
                                    ref.delete_node(sel);

                                }
                            }
                        };
                    }
                },
Developer
  • 2,731
  • 2
  • 41
  • 71
  • your `rename` and `delete` actions works fine but `create` action doesn't work properly. when creates a new node then want to create another for different one, new node added to previously selected node. – Ahmad Badpey Mar 27 '16 at 09:24
7

Updated code for last version

"contextmenu":{         
    "items": function($node) {
        var tree = $("#tree").jstree(true);
        return {
            "Create": {
                "separator_before": false,
                "separator_after": false,
                "label": "Create",
                "action": function (obj) { 
                    $node = tree.jstree('create_node', $node);
                    tree.jstree('edit', $node);
                }
            },
            "Rename": {
                "separator_before": false,
                "separator_after": false,
                "label": "Rename",
                "action": function (obj) { 
                    tree.jstree('edit', $node);
                }
            },                         
            "Remove": {
                "separator_before": false,
                "separator_after": false,
                "label": "Remove",
                "action": function (obj) { 
                    tree.jstree('delete_node', $node);
                }
            }
        };
    }
}
Askar Amirov
  • 71
  • 1
  • 2
3

More readable example

 var tree = $('#treeDiv').jstree({
        "plugins": ["contextmenu"],
        "contextmenu": {
            "items": function ($node) {
                return {
                    "create": {
                        "separator_before": false,
                        "separator_after": false,
                        "label": "Create",
                        "action": function (obj) {
                            // action code here
                        }
                    }
                };
            }
        }
    });
Irfan Ashraf
  • 2,430
  • 21
  • 20
1
"contextmenu": {
  "items": function ($node) {
    var tree = $("#tree").jstree(true);
    return {
      "Create": {
        "separator_before": false,
        "separator_after": true,
        "label": "Create",
        "action": false,
        "submenu": {
          "File": {
            "seperator_before": false,
            "seperator_after": false,
            "label": "File",
            action: function (obj) {
              $node = tree.create_node($node, {
                text: 'New File',
                type: 'file',
                icon: 'glyphicon glyphicon-file'
              });
              tree.deselect_all();
              tree.select_node($node);
            }
          },
          "Folder": {
            "seperator_before": false,
            "seperator_after": false,
            "label": "Folder",
            action: function (obj) {
              $node = tree.create_node($node, {
                text: 'New Folder',
                type: 'default'
              });
              tree.deselect_all();
              tree.select_node($node);
            }
          }
        }
      },
      "Rename": {
        "separator_before": false,
        "separator_after": false,
        "label": "Rename",
        "action": function (obj) {
          tree.edit($node);
        }
      },
      "Remove": {
        "separator_before": false,
        "separator_after": false,
        "label": "Remove",
        "action": function (obj) {
          tree.delete_node($node);
        }
      }

    }
  }
}
rnnhm
  • 53
  • 6
0
$("#jstree").jstree({
    "core" : {
        "themes" : { "responsive": false },            
        "check_callback" : true,
        'data': [...],
    },
    "types" : {
        "default" : {
            "icon" : "fa fa-circle text-success",
            "state": { "opened": true },
        }        
    },
    "state" : { "key" : "demo2" },
    "plugins" : ["unique","dnd", "state", "types", "wholerow", "contextmenu"],
    "contextmenu": {
        "items": function(n){
            var tmp = $.jstree.defaults.contextmenu.items();
            tmp.create.label = `{{__('my.create')}}`;
            tmp.rename.label = `{{__('my.rename')}}`;
            tmp.remove.label = `{{__('my.remove')}}`;
            tmp.ccp.label = `{{__('my.edit')}}`;
            tmp.ccp.submenu.cut.label = `{{__('my.cut')}}`;
            tmp.ccp.submenu.copy.label = `{{__('my.copy')}}`;
            tmp.ccp.submenu.paste.label = `{{__('my.paste')}}`;
            return tmp;
        }
    }
});
Akın Köker
  • 405
  • 5
  • 7