Search code examples
javascriptjquerymysqljstree

Lazy loading JSTREE


I created a diagram of a tree in jstree. Because I have a lot of nodes data I want the load to be lazy. How is it possible that with every click on a parent there will be a call to mysql database and the children's will be retrieved?

Like this idea: How to only display a TreeView expand sign [+] if children exist

Thank you!


Solution

  • $('#tree').jstree({
        'core': {
            'data': {
                // This is the API URL for processing child nodes
                'url': '/get/children/',
                // This method is used to to prepare query data
                'data': function (node) {
                    // This will add a query `?id=node_id_value`
                    // Add your own query data as per the requirement of API endpoint for processing
                    return { 'id': node.id };
                }
            }
        }
    });
    

    The url property is to mention the URL to contact for children nodes, and the data function which runs over a clicked tree node to prepare query data to pass with URL.

    Below are demo API endpoints from JSTREE for lazy loading

    Root Node

    API endpoint: https://www.jstree.com/fiddle/?lazy&id=%23

    [
        {
            "id": 1,
            "text": "Root node",
            // Children of root node
            "children": [
                {
                    "id": 2,
                    "text": "Child node 1",
                    "children": true // Child node 1 still has to be loaded lazily
                },
                {
                    "id": 3,
                    "text": "Child node 2"
                }
            ]
        }
    ]
    

    Child node 1

    API endpoint: https://www.jstree.com/fiddle/?lazy&id=2

    This will load the children node details, as the id 2 is of Child node 1

    Notes:

    • Node without children property is considered as the final node in the tree branch.
    • children property of a node is either an array of nodes to render child nodes immediately or, a boolean true for loading children lazily.
    • Each node must have an id which is to be unique per node, so that the node id could be used at API endpoint for processing respective child nodes.

    Added a sample snippet to identify whether the selected node has children or not with event changed.jstree

    $(function () {
        $('#lazy').jstree({
            'core': {
                'data': {
                    "url": "//www.jstree.com/fiddle/?lazy",
                    "data": function (node) {
                        return { "id": node.id, "noCache": Date.now() };
                    }
                }
            }
        });
    
        $('#lazy').on('changed.jstree', function (e, data) {
            if (data.selected.length) {
                var selected = data.instance.get_node(data.selected[0]);
                var hasChildren = !selected.state.loaded || selected.children.length > 0;
                console.log(`Selected = ${selected.text}, hasChildren = ${hasChildren}`);
            }
        })
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.11/jstree.min.js" integrity="sha512-bU6dl4fd2XN3Do3aWypPP2DcKywDyR3YlyszV+rOw9OpglrGyBs6TyTsbglf9umgE+sy+dKm1UHhi07Lv+Vtfg==" crossorigin="anonymous"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.11/themes/default/style.min.css" integrity="sha512-P8BwDSUInKMA7I116Z1RFg/Dfk85uFdliEUYO7vQlwtxLVMNvZimfMAQsaf++9EhlAGOVX6yhDQAIY3/70jDUg==" crossorigin="anonymous" />
    
    
    <div id="lazy" class="demo"></div>

    Hope that this information helps.