adamdport
adamdport

Reputation: 12633

How do I programmatically select Material Tree nodes with SelectionModel?

I have a tree with checkboxes (let's use Material's example here). I'd like the fruit nodes to begin checked. How do I check those nodes?

I see that SelectionModel has a select() method that the example passes a node. But in the example, the data the tree is made of is an array of TodoItemNode, but the SelectionModel contains TodoItemFlatNode. The transformer method in the example can "flatten" my node (ie. convert TodoItemNode to TodoItemFlatNode), but that would return a new instance.

How can I programmatically select mat-tree checkboxes to match my data?

Upvotes: 11

Views: 23795

Answers (2)

Nyerguds
Nyerguds

Reputation: 5629

For NestedTreeControl, where dataNodes is undefined, you can just go through the datasource instead. This can be done using a recursive function, demonstrated here by looking for it by an id property on a TreeItem class used to populate the tree. Of course your lookup method can differ depending on the class you have for that.

Once you find the correct node in the DataSource data, you can create an array containing the found object and return it. The previous levels of the recursion can then add their own level's found item to the end, so the final result is an array containing the entire sequence to expand, in reverse order, with index 0 as the deepest node.

expandTreeToNode(nodeId: number) {
    let selectNode: TreeItem[] | null = this.findTreeNode(this.nestedDataSource.data, nodeId);
    if (selectNode != null && selectNode.length > 0) {
        // expand the returned tree, from shallowest to deepest level
        for (let i : number = selectNode.length - 1; i >= 0; --i)
            this.nestedTreeControl.expand(selectNode[i]);
        // function to make stuff happen when you click on a node.
        this.setSelectedNode(selectNode[0]);
    }
}

findTreeNode(collection: TreeItem[], nodeId: number) : TreeItem[] | null
{
    for (let i = 0; i < collection.length; ++i)
    {
        let item : TreeItem = collection[i];
        if (item.id == nodeId)
            return new Array(item);
        let chItem : TreeItem[] | null = this.findTreeNode(item.children, nodeId);
        if (chItem != null) {
            chItem[chItem.length] = item;
            return chItem;
        }
    }
    return null;
}

Upvotes: 0

Marshal
Marshal

Reputation: 11081

To pre-select the fruits node implement the following in an ngAfterViewInit for the TreeChecklistExample class in the attached stackblitz example.

  • This will loop through the dataNodes in the treeControl
  • If item == 'Fruits' select node and expand
  • Also if item == 'Groceries' expand node as it is the parent of Fruits.

    ngAfterViewInit() {
        for (let i = 0; i < this.treeControl.dataNodes.length; i++) {
          if (this.treeControl.dataNodes[i].item == 'Fruits') {
            this.todoItemSelectionToggle(this.treeControl.dataNodes[i]);
            this.treeControl.expand(this.treeControl.dataNodes[i])
          }
          if (this.treeControl.dataNodes[i].item == 'Groceries') {
            this.treeControl.expand(this.treeControl.dataNodes[i])
          }
        }
      }
    

Stackblitz

https://stackblitz.com/edit/angular-j2nf2r?embed=1&file=app/tree-checklist-example.html


Upvotes: 24

Related Questions