Bootstrap treeview performance issue

1.2k views Asked by At

I am using this plugin for showing a tree.

Does it have any functionality which will check all child nodes when parent node is checked?

Currently I can't find any way to do this.

To achieve this functionality I have written recursive function to find each node under root and check using checkNode function.

I see a performance issue when depth of the tree is more than 3 for around 150 nodes. On investigation I found checkNode function in bootstrap-treeview.js uses render each time node is checked, can anyone tell me the use of this render function?

Can we remove use of render?

2

There are 2 answers

0
Patrick Green On

I was struggling with performance using a recursive solution as well, but I found a more efficient alternative. The call to checkAll is fast, even with large trees, because it only makes a single call to render, while a recursive implementation of this checking using checkNode will call render many times unnecessarily, as you pointed out.

I couldn't find this in the documentation, but I noticed that checkNode calls forEachIdentifier in its implementation, the same as checkAll, so you can actually pass in an array of nodes or nodeIds, instead of just a single nodeId, and it will only call render only once, after all the nodes are checked. The only difference for checkAll is that it specifically passes in all the nodeIds in the tree.

So you can just add some code in your event handler to generate the list of nodeIds for all nodes underneath the parent, by looking at the id of the last child node and building a range, then call checkNode once.

function onNodeChecked(event, node_data) {
    var first_index, last_index, last_node, nodes, range, i;
    nodes = node_data.nodes;
    if (nodes != null) {
      first_index = node_data.nodeId;
      last_node = nodes[nodes.length - 1];
      while (last_node.nodes != null) {
        nodes = last_node.nodes;
        last_node = nodes[nodes.length - 1];
      }
      last_index = last_node.nodeId;
      range = [];
      for (i = first_index; i <= last_index ; i++) {
        range.push(i);
      }
      return $('#tree').treeview('checkNode', [range, {silent: true}]);
    }
}

Edit: revised code to properly handle the case where the last child has children.

0
Mehul Jethloja On

Try this.

Edit bootstrap treeview js files.

find toggleCheckedState function and replace with below

Tree.prototype.toggleCheckedState = function (node, options) {
    if (!node) return;
    this.setCheckedState(node, !node.state.checked, options);
    if (node.nodes && !options.ignoreChildren) {
        $.each(node.nodes, $.proxy(function (index, node1) {
            this.toggleCheckedState(node1,_default.options);
        }, this));
    }
};