javascriptjqueryajaxjstree

Set jsTree Node to "Undetermined" State


I'm using jsTree to show a tree with checkboxes. Each level of nodes is loaded on-demand using the json_data plugin.

If a node's descendent is checked, then that node should be in an "undetermined state" (like ACME and USA).

Checked Descendent in jsTree

The problem is, the tree starts out collapsed. ACME looks unchecked but should be undetermined. When I finally expand to a checked node, jsTree realizes the ancestors should be undetermined.

Expanding to checked node fixes the problem

So I need to be able to put a checkbox in the undetermined state without loading its children.

With jsTree you can pre-check a box by adding the jstree-checked class to the <li>. I tried adding the jstree-undetermined class, but it doesn't work. It just puts them in a checked state.

Here's my code:

$("#tree").jstree({
    plugins: ["json_data", "checkbox"],
    json_data: {
        ajax: {
            url: '/api/group/node',
            success: function (groups) {
                var nodes = [];
                for (var i=0; i<groups.length; i++) {
                    var group = groups[i];

                    var cssClass = "";
                    if(group.isSelected)
                        cssClass = "jstree-checked";
                    else if(group.isDecendantSelected)
                        cssClass = "jstree-undetermined";

                    nodes.push({
                        data: group.name,
                        attr: { 'class': cssClass }
                    });
                }
                return nodes;
            }
        }
    }
})

My Question

How do I set a node to the undetermined state?


Solution

  • I had the same problem and the solution I found was this one:

    var tree = $("#tree").jstree({
        plugins: ["json_data", "checkbox"],
        json_data: {
            ajax: {
                url: '/api/group/node',
                success: function(groups) {
                    var nodes = [];
                    for (var i = 0; i < groups.length; i++) {
                        var group = groups[i];
                        var checkedState = "false";
                        if (group.isSelected)
                            checkedState = "true";
                        else if (group.isDecendantSelected)
                            checkedState = "undetermined";
                        nodes.push({
                            data: group.name,
                            attr: { 'checkedNode': checkedState }
                        });
                    }
                    return nodes;
                },
                complete: function () {
                    $('li[checkedNode="undetermined"]', tree).each(function () {
                        $(this).removeClass('jstree-unchecked').removeClass('jstree-checked').addClass('jstree-undetermined');
                    });
                    $('li[checkedNode="true"]', tree).each(function () {
                        $(this).removeClass('jstree-unchecked').removeClass('jstree-undetermined').addClass('jstree-checked');
                    });
                    $('li[checkedNode="false"]', tree).each(function () {
                        $(this).removeClass('jstree-checked').removeClass('jstree-undetermined').addClass('jstree-unchecked');
                    });
                }
            }
        }
    });
    

    Hope it helps you!