15

I have a jstree with checkbox for every nodes. I want to achieve the following. Let me know which method or part of api helps us to do that.

  1. I do not want to check any child nodes when parent node is selected. Currently all the children gets selected.
  2. If any child node is checked then check all its parent node. Currently parent nodes get partially checked (square). I want to remove partial selection completely. That is I want to completely alter behavior of jstree checkboxes.

I searched API docs but found nothing.

Ashwin
  • 12,081
  • 22
  • 83
  • 117

4 Answers4

9

Take a look at the real_checkboxes options. This might get you started:

        $("#jstree").jstree({
           "checkbox": {
              real_checkboxes: true,
              real_checkboxes_names: function (n) {
                 var nid = 0;
                 $(n).each(function (data) {
                    nid = $(this).attr("nodeid");
                 });
                 return (["check_" + nid, nid]);
              },
              two_state: true
           },
           "plugins": ["themes", "json_data", "ui", "checkbox"]
        })
        .bind('open_node.jstree', function (e, data) {
           $('#jstree').jstree('check_node', 'li[selected=selected]');
        })

You'll probably need to change the bind behaviour so that it checks the parent when a child is checked.

chris
  • 36,094
  • 53
  • 157
  • 237
  • @KrishanGopal take a look at [my answer](http://stackoverflow.com/a/30226390/573634) as it pertains to the most recent version of jstree (3.1.1 as of writing this). I realize you may not need this anymore since it's been two years, but maybe it'll help someone else! – Hanna May 13 '15 at 22:44
9

As of JSTree version 3.1.1 here is what I would do:

$('#data').jstree({
    'core' : {
        'data' : [
            { "text" : "Root node", "children" : [
                    { "text" : "Child node 1" },
                    { "text" : "Child node 2" }
            ]},
            { "text" : "Root node 2", "children" : [
                    { "text" : "Child node 1" },
            ]}
        ]
    },
    'checkbox': {
        three_state: false,
        cascade: 'up'
    },
    'plugins': ["checkbox"]
});

JSFiddle Demo

Note that the magic here happens with the checkbox parameters.

From the documentation:

three_state: a boolean indicating if checkboxes should cascade down and have an undetermined state. Defaults to true.


cascade: This setting controls how cascading and undetermined nodes are applied. If 'up' is in the string - cascading up is enabled, if 'down' is in the string - cascading down is enabled, if 'undetermined' is in the string - undetermined nodes will be used. If three_state is set to true this setting is automatically set to 'up+down+undetermined'. Defaults to ''.

This documentation was found inside of the source code for v.3.1.1

EDIT I just checked v3.3.0, and although the documentation changed for these attributes (in my opinion, for the worse), the code works just the same. In the meantime though it looks like these attributes are listed in their API: three_state and cascade and as of writing this seem to have better documentation than the source code.

Keep in mind that if you have multiple child nodes underneath a parent, checking just one of the children will not check the parent. All nodes must be checked to take effect on the parent.

Hope this helps!

Hanna
  • 10,315
  • 11
  • 56
  • 89
  • How to catch the select and unselect events? – Magno C May 16 '16 at 16:48
  • 1
    Please [refer to their documentation](https://www.jstree.com/docs/events/) -- just instead of doing `changed.jstree` you would use their `select_node.jstree` or `deselect_node.jstree` -- for other events, [see their API](https://www.jstree.com/api/#/?q=.jstree%20Event) – Hanna Jun 02 '16 at 00:50
  • >> _Keep in mind that if you have multiple child nodes underneath a parent, checking just one of the children will not check the parent. All nodes must be checked to take effect on the parent._ Wow! I spent too much time before figure out that! Can i do something to check parent even if only one child node selected? – Zhivago Oct 18 '16 at 16:32
  • You mean a full check, not a partial check? Not that I know of. Though if you needed that you could try to treat a partial check as a full check (and then modify the UI so that partial checks look like full checks). That may work for you. – Hanna Oct 21 '16 at 03:01
2

This is what I used. Not as terse as the other ones but works:

$('#jstree').jstree( {
  "plugins" : ["checkbox"],
  "checkbox": {
    "three_state": false
  }
}).on("select_node.jstree", function (e, data) {
  var selectedNode;
  if (data.selected.length == 1) {
    lastSelected = data.selected.slice(0);
    selectedNode = data.selected[0];
  } else {
    // Get the difference between lastselection and current selection
    selectedNode = $.grep(data.selected, function(x) {return $.inArray(x, lastSelected) < 0});
    lastSelected = data.selected.slice(0); // trick to copy array
  }
  // Select the parent
  var parent = data.instance.get_node(selectedNode).parent;
  data.instance.select_node(parent);
}).on("deselect_node.jstree", function (e, data) {
  // Get the difference between lastselection and current selection
  var deselectedNode = $.grep(lastSelected,function(x) {return $.inArray(x, data.selected) < 0})
  , children = data.instance.get_children_dom(deselectedNode);
  if (children.length) {
    children.each(function(i, a) {
      data.instance.deselect_node(a);
      lastSelected = data.selected.slice(0);
    });
  } else {
    lastSelected = data.selected.slice(0);
  }
});
Saad Farooq
  • 13,172
  • 10
  • 68
  • 94
1

I had similar requirement as per the question and tried @chris answer above but no success with suggested answer.

here is what I did to make this working

.bind('check_node.jstree', function (e, data) { //check all parent nodes
    //var currentNode = data.rslt.obj.attr("id");
        var parentNode =  data.rslt.obj.attr("parent_id")
        $('#demo').jstree('check_node', '#'+parentNode);
})
.bind('uncheck_node.jstree', function (e, data) {//uncheck all child nodes
    var allChildNodes = data.inst._get_children(data.rslt.obj);
        allChildNodes.each(function(idx, listItem) { 
            $('#demo').jstree('uncheck_node', '#'+$(listItem).attr("id"));
        });
})
.jstree({ 
// List of active plugins
    "checkbox": {
        real_checkboxes: true,
            two_state: true,
            checked_parent_open: true,
            override_ui:true
    },
    "plugins" : [ 
        "themes","json_data","ui","cookies","dnd","search","types","hotkeys","contextmenu","crrm", "checkbox"
    ]
})
Krishan Gopal
  • 4,073
  • 1
  • 16
  • 19