Angular 6+Angular Material使用mat-tree报错:Could not find a tree control for the tree
Hey there, let's get that tree component working properly! The error you're seeing happens because Angular Material's <mat-tree> requires a TreeControl instance to manage the tree's state (like expanding/collapsing nodes, tracking node hierarchy, etc.). Your current code only has the basic tree and node elements, but no connection to the control that makes the tree functional.
Here's a step-by-step solution to fix this:
1. Import required modules in your component and module
First, make sure you've imported the necessary tree-related modules in your Angular module (e.g., AppModule or your feature module):
import { NgModule } from '@angular/core'; import { MatTreeModule } from '@angular/material/tree'; import { CdkTreeModule } from '@angular/cdk/tree'; import { MatIconModule } from '@angular/material/icon'; // Needed for expand/collapse icons @NgModule({ imports: [ MatTreeModule, CdkTreeModule, MatIconModule, // ... other modules your app needs ] }) export class YourModule { }
Then, in your component class, import the TreeControl and DataSource. We'll use a nested tree as an example (flat trees work similarly with FlatTreeControl):
import { Component } from '@angular/core'; import { NestedTreeControl } from '@angular/cdk/tree'; import { MatTreeNestedDataSource } from '@angular/material/tree'; // Define a simple interface for your tree nodes interface TreeItem { name: string; children?: TreeItem[]; } // Sample tree data (replace with your own data) const TREE_DATA: TreeItem[] = [ { name: 'Parent Node', children: [ { name: 'Child Node 1' }, { name: 'Child Node 2' } ] } ]; @Component({ selector: 'app-your-tree-component', templateUrl: './your-tree-component.html' }) export class YourTreeComponent { // Initialize the tree control - it uses a function to fetch child nodes treeControl = new NestedTreeControl<TreeItem>(node => node.children); // Initialize the data source to feed data to the tree dataSource = new MatTreeNestedDataSource<TreeItem>(); constructor() { // Assign your tree data to the data source this.dataSource.data = TREE_DATA; } // Helper function to check if a node has children (for expandable nodes) hasChild = (_: number, node: TreeItem) => !!node.children && node.children.length > 0; }
2. Update your template to bind the control and data source
Modify your template to connect the treeControl and dataSource to <mat-tree>, and add templates for both leaf and expandable nodes:
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl"> <!-- Template for leaf nodes (no children) --> <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle> <li class="mat-tree-node"> <button mat-icon-button disabled></button> <!-- Empty button for consistent spacing --> {{ node.name }} </li> </mat-tree-node> <!-- Template for expandable nodes (with children) --> <mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild"> <li> <div class="mat-tree-node"> <button mat-icon-button matTreeNodeToggle [attr.aria-label]="'Toggle ' + node.name"> <mat-icon> {{ treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right' }} </mat-icon> </button> {{ node.name }} </div> <ul [class.mat-tree-invisible]="!treeControl.isExpanded(node)"> <ng-container matTreeNodeOutlet></ng-container> </ul> </li> </mat-nested-tree-node> </mat-tree>
Why this works
- The
TreeControlkeeps track of which nodes are expanded/collapsed and understands the tree's hierarchy. - The
DataSourceprovides the actual data to the tree component. - The
*matTreeNodeDefdirectives define how different types of nodes (leaf vs expandable) should be rendered.
Once you implement this, the error should disappear, and your mat-tree will work as expected!
内容的提问来源于stack exchange,提问作者Prasad Shinde

