angular-tree-component: Slow preformance on expand and select checkboxes

Hi,

I know there are ALOT of posts related to this issue but I still didn’t find a proper answer for this problem. I’m using this (GREAT ! ) module with nodes list ~10K . When trying to select a checkbox with a list of >1K - the system is lagging. In addition , using treeModel.expandAll() - is also lagging. Also programically using those lines are codes are showing poor preformance :

selectAllNodes() {
        const firstNode = this.tree.treeModel.getFirstRoot();
        firstNode.setIsSelected(true);
    }

    deselectAllNodes() {
        const firstNode = this.tree.treeModel.getFirstRoot();
        firstNode.setIsSelected(false);
    }

It is not clear if there is some kind of fix for those problems in the near future (or not…).

Plunker : https://plnkr.co/edit/yYRiJtGmpvG49JOvLw2m?p=info

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Comments: 23 (4 by maintainers)

Most upvoted comments

Hello I don’t know if it helps but also with huge trees expandAll and collapseAll can be quite fast with some drawbacks which @adamkleingit may be able to find and explain.

  public setExpandedNodes(expandedNodeIds: any) {
    this.tree.treeModel.expandedNodeIds = expandedNodeIds;
    this.refresh();
  }

  public collapseAll() {
    let expandedNodeIds: any = {};
    this.setExpandedNodes(expandedNodeIds);
  }
  
  public expandAll() {
    let expandedNodeIds: any = {};
    for (let node of this.tree.treeModel.roots) {
      expandedNodeIds = this.updateNode(node, expandedNodeIds, true)
    }
    this.setExpandedNodes(expandedNodeIds);
  }

  private updateNode(node: TreeNode, expandedNodeIds: any, expand: boolean) {
    let newExp = expandedNodeIds
    let children = node.children
    if (children) {
      for (let child of children) {
        newExp = this.updateNode(child, newExp, expand);
      }
    }
    if (node.hasChildren) {
      return Object.assign({}, newExp, {[node.id]: expand});
    }
    return newExp;
  }

One problem is that no event is fired for the expand and collapse but this may not be a problem for you

I know this thread is old but I run into same issue. Here’s snippet for checkbox performance issue (Select all) that you can pass with options I managed to reduce delay from 5-10 sec to ~160ms (I have ~2.5k elements in tree).

const actionMapping: IActionMapping = {
    mouse: {
        checkboxClick: (tree: TreeModel, node: TreeNode, $event: any) => {
            if (!node) {
                return;
            }
            const value = !node.isSelected;
            const selectedLeadNodes = tree.selectedLeafNodeIds;
            setNodeSelected(tree, node, value);
            tree.selectedLeafNodeIds = Object.assign({}, selectedLeadNodes, {[node.id]: value});

            function setNodeSelected(tree, node, value) {
                if (node.isSelectable()) {
                    selectedLeadNodes[node.id] = value;
                } else {
                    node.visibleChildren.forEach((child) => setNodeSelected(tree, child, value));
                }
            }
        }
    }
};

const options: ITreeOptions = {
    useCheckbox: true,
    useVirtualScroll: true,
    nodeHeight: 25,
    actionMapping
};

This works fast: this.tree.treeModel.doForAll((node: TreeNode) => node.isSelected && node.setIsSelected(false));

@nshelms I had a look in the code but please be aware I’m not a contributor of this project, I’m just user of this lib as you are. So I can’t tell you which unwanted side effects this has. And as long as Adam or any other official contributor with knowledge of the code tells something about this, my ideas can bring more harm then help.

So in the treeModel class there is the method/function

@action setSelectedNode(node, value) {
    this.selectedLeafNodeIds = Object.assign({}, this.selectedLeafNodeIds, {[node.id]: value});

    if (value) {
      node.focus();
      this.fireEvent({ eventName: TREE_EVENTS.select, node });
    } else {
      this.fireEvent({ eventName: TREE_EVENTS.deselect, node });
    }
}

So i assume that you may do the same as in my expand all method.

public selectAll() {
    let selectedLeafNodeIds: any = {};
    for (let node of this.tree.treeModel.roots) {
      selectedLeafNodeIds = this.updateSelectedNodes(node, selectedLeafNodeIds, true)
    }
    this.tree.treeModel.selectedLeafNodeIds = selectedLeafNodeIds;
    this.tree.sizeChanged();
  }

  private updateSelectedNodes(node: TreeNode, selectedLeafNodeIds: any, expand: boolean) {
    let newSel = selectedLeafNodeIds
    
    if (node.hasChildren()) {
      let children = node.children
      for (let child of children) {
        newExp = this.updateSelectedNodes(child, newSel, expand);
      }
    } else {
      return Object.assign({}, newSel, {[node.id]: expand});
    }
    return newExp;
  }

I haven’t tested this code at all, so please try to run it yourself. I just had a look in the code and made some assumptions. Maybe this isn’t working at all

BW