Lars Rødal
Lars Rødal

Reputation: 876

Expand/Collapse Material Tree using data boolean (Angular 7)

I am trying to get a Material Tree working with booleans from it's datasource. I am filtering datasource.data on input, which causes the tree to collapse every time the user inputs something. To avoid this, I would like to use a boolean in the specific row to expand/collapse the material tree. I've done this successfully with the material table, but am not able to get it working with the tree. This is what I have so far:

HTML-file:

<mat-tree [dataSource]="nestedDataSource" [treeControl]="nestedTreeControl" class="example-tree">
  <mat-tree-node *matTreeNodeDef="let node">
    <li class="mat-tree-node">
      <button mat-icon-button disabled></button>
      {{node.name}}
    </li>
  </mat-tree-node>

  <mat-nested-tree-node *matTreeNodeDef="let node; when: hasNestedChild">
    <li>
      <div class="mat-tree-node">
        <button mat-icon-button
                [attr.aria-label]="'toggle ' + node.name"
                click="changeState(node)">
          <mat-icon class="mat-icon-rtl-mirror">
            {{node.expanded ? 'expand_more' : 'chevron_right'}}
          </mat-icon>
        </button>
        {{node.name}} ({{node.expanded}})
      </div>
      <ul [class.example-tree-invisible]="node.expanded">
        <ng-container matTreeNodeOutlet></ng-container>
      </ul>
    </li>
  </mat-nested-tree-node>
</mat-tree>

TS-file:

import {NestedTreeControl} from '@angular/cdk/tree';
import {Component, Injectable} from '@angular/core';
import {MatTreeNestedDataSource} from '@angular/material/tree';
import {BehaviorSubject} from 'rxjs';

/**
 * Json node data with nested structure. Each node has a filename and a value or a list of children
 */
export class FileNode {
  childGroups: FileNode[];
  name: string;
  expanded: boolean;
}

/**
 * The Json tree data in string. The data could be parsed into Json object
 */
const TREE_DATA = [
  {
  'name': 'Group 1',
  'expanded': false,
  'childGroups': [
    {
      'name': 'Childgroup 1',
      'expanded': false,
      'childGroups': []
    },
    {
      'name': 'Childgroup 2',
      'expanded': false,
      'childGroups': [
        {
          'name': 'Child of child',
          'expanded': false,
          'childGroups': []
        }
      ]
    }
    ]
  },
    {
  'name': 'Group 2',
  'expanded': false,
  'childGroups': [
    {
      'name': 'Childgroup 1',
      'expanded': false,
      'childGroups': []
    },
    {
      'name': 'Childgroup 2',
      'expanded': false,
      'childGroups': [
        {
          'name': 'Child of child',
          'expanded': false,
          'childGroups': []
        }
      ]
    }
    ]
  },
    {
  'name': 'Group 3',
  'expanded': false,
  'childGroups': [
    {
      'name': 'Childgroup 1',
      'expanded': false,
      'childGroups': []
    },
    {
      'name': 'Childgroup 2',
      'expanded': false,
      'childGroups': [
        {
          'name': 'Child of child',
          'expanded': false,
          'childGroups': []
        }
      ]
    }
    ]
  },
]

@Component({
  selector: 'tree-nested-overview-example',
  templateUrl: 'tree-nested-overview-example.html',
  styleUrls: ['tree-nested-overview-example.css']
})
export class TreeNestedOverviewExample {
  nestedTreeControl: NestedTreeControl<FileNode>;
  nestedDataSource: MatTreeNestedDataSource<FileNode>;

  constructor() {
    this.nestedTreeControl = new NestedTreeControl<FileNode>(this._getChildren);
    this.nestedDataSource = new MatTreeNestedDataSource();
    this.nestedDataSource.data = TREE_DATA;
  }

  hasNestedChild = (_: number, nodeData: FileNode) => 
  nodeData.childGroups.length > 0;

  private _getChildren = (node: FileNode) => node.childGroups;

  changeState(node) {
    console.log(node);
    node.expanded = !node.expanded;
  }
}

Stackblitz

Upvotes: 4

Views: 14164

Answers (1)

Gordon Westerman
Gordon Westerman

Reputation: 1115

From the Angular documentation on User Input:

To bind to a DOM event, surround the DOM event name in parentheses and assign a quoted template statement to it.

All you need to do is change click to (click).

DEMO

Upvotes: 5

Related Questions