I am using mat tree toggle from material angular and finding it hard to toggle between expand and collapse. Eg. If I click on one of the items in tree, it should expand and then if I click on another to expand, it should collapse the previously open. Like we do in case of accordions. All the help is highly appreciated. Attaching my code below
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
<!-- This is the tree node template for leaf nodes -->
<mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding
[style.background]="treeControl.isExpanded(node) ? '#DEEAFF' : ''">
<mat-list-item routerLink="{{node.path}}">{{node.name}}</mat-list-item>
</mat-tree-node>
<!-- This is the tree node template for expandable nodes -->
<mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding
[style.background]="treeControl.isExpanded(node) ? '#DEEAFF' : ''">
<mat-list-item>
<button mat-icon-button matTreeNodeToggle disableRipple [attr.aria-label]="'toggle ' node.name">
{{node.name}}
</button>
</mat-list-item>
<mat-icon color="primary">
{{treeControl.isExpanded(node) ? 'expand_less' : 'expand_more'}}
</mat-icon>
</mat-tree-node>
</mat-tree>
CodePudding user response:
- Add a click event to matTreeNodeToggle to trigger the collapsing logic
- Fetch the parent node and collapse all the descendants
- Expand only the clicked node and the parent node if available
nodeClicked(node) {
if (this.treeControl.isExpanded(node)) {
let parent = null;
let index = this.treeControl.dataNodes.findIndex((n) => n === node);
for (let i = index; i >= 0; i--) {
if (node.level > this.treeControl.dataNodes[i].level) {
parent = this.treeControl.dataNodes[i];
break;
}
}
if(parent){
this.treeControl.collapseDescendants(parent);
this.treeControl.expand(parent);
} else {
this.treeControl.collapseAll()
}
this.treeControl.expand(node);
}
}
<button mat-icon-button matTreeNodeToggle disableRipple [attr.aria-label]="'toggle ' node.name" (click)=nodeClicked(node)>
{{node.name}}
</button>