jsTree can't select leafs

706 views Asked by At

so I have here a jsTree instance, which is working fine. I'm dynamically storing datasets (with jquery .attr() and .data() ) in the list items, the html set is precoded (no loading via ajax or whatever).

the structure looks like this:

<ul>
<li>Node1
    <ul>
        <li>Node2
            <ul>
                <li data-material-id="bpch1u1">Leaf 1</li>
                <li data-material-id="bpch1u2">Leaf 2</li>
            </ul>
        </li>
    </ul>
</li>

Then i have a button:

<button type="button" class="btn btn-primary" onclick="openMaterial($(this))">Open Material now</button>

while listening to an external script, the button is provided with a data-material attribute. The attribute is set correctly and i am able to read it.

what i want now is that on click of the button openMaterial() it should open the corresponding leaf with data-material-id= button-material

my function looks like this:

function openMaterial(el)
    {
        //get treenode with material id
        var node = $('li[data-material-id="' + el.data('material') + '"]');
    }

node holds an jQuery object after the call, but sadly its empty (holding the body). I believe this is because any not-opened nodes or leafs of the jsTree are not in the DOM. Means even if I open them and close them again, or load them they don't appear in the DOM.

I tried the jsTree functions open_all and load_all and they seem to work, but i still can't get the leaf. is there another option to get the corresponding leaf with just the data-attribute?

EDIT:

Another try using the built-in jsTree function get_node:

var node = $('#material_list').jstree('get_node','li[data-material-id="' + el.data('material') + '"]');

It's not working at all. If I call it when all nodes are closed it returns "false", if the nodes and leafs are opened (programmatically or manual) it returns the correct leaf.

2

There are 2 answers

0
Jan Schuermann On BEST ANSWER

I got two solutions for this now:

-Bubble down the tree progressively (open one node after another)

-Open all nodes, fetch the node, fire the event, close all nodes again

I haven't tried the bubbling down yet because the second option seems more efficient to me, since i only need the data-material attribute of the leaf.

So this can be kept in just one line with one jQuery selector:

$('#material_list').jstree('open_all')
    .jstree('select_node','li[data-material-id="' + el.data('material') + '"]')
    .jstree('close_all');
3
vakata On

Another way is to traverse the internal jstree storage and get your items from there (and select them or simply reveal them):

var instance = $('#material_list').jstree(true),
    material = el.data('material'),
    i;
for(i in instance._model.data) {
    if(i !== '#' && instance._model.data.hasOwnProperty(i)) {
        if(instance._model.data[i].li_attr['data-material-id'] === material) {
            instance.select_node(i); // use this to reveal the node and select it
            instance._open_to(i); // use this to reveal the node
            instance.select_node(i, false, true); // use this to select the node without revealing it
        }
    }
}