基于选中Mat-tree节点动态展示Mat-table数据的实现问题
Alright, let's fix this up step by step. I see two core issues here: you can't access the selected node's data in the right panel, and you haven't integrated the Mat-table to display the node's children yet. Let's tackle these one by one.
Step 1: Update Your Component Class (app.component.ts)
First, we need to add properties to track the selected node, handle the table data source, and add a method to trigger updates when a node is clicked. Here's the revised code:
import { Component } from '@angular/core'; import { NestedTreeControl } from '@angular/cdk/tree'; import { MatTreeNestedDataSource } from '@angular/material/tree'; import { MatTableDataSource } from '@angular/material/table'; // Define your node structure to match your data interface TreeNode { name: string; children?: TreeNode[]; } @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { treeControl = new NestedTreeControl<TreeNode>(node => node.children); dataSource = new MatTreeNestedDataSource<TreeNode>(); // Table-related setup tableDataSource = new MatTableDataSource<TreeNode>(); displayedColumns: string[] = ['name']; // Columns to show in the table selectedNode: TreeNode | null = null; // Stores the currently clicked node // Replace this with your actual tree data TREE_DATA: TreeNode[] = [ { name: 'Root Node 1', children: [ { name: 'Child 1.1' }, { name: 'Child 1.2', children: [{ name: 'Grandchild 1.2.1' }] } ] }, { name: 'Root Node 2', children: [{ name: 'Child 2.1' }, { name: 'Child 2.2' }] } ]; constructor() { this.dataSource.data = this.TREE_DATA; } hasChild = (_: number, node: TreeNode) => !!node.children && node.children.length > 0; // Triggered when a tree node is clicked onNodeClick(node: TreeNode) { this.selectedNode = node; // Update table data with the node's children (empty array if no children) this.tableDataSource.data = node.children || []; } }
Step 2: Revise the Template (app.component.html)
Now we'll fix the template to properly handle node clicks, display the selected node's name, and integrate the Mat-table to show child nodes:
<div class="main-wrap" style="display: flex; gap: 2rem; padding: 2rem;"> <div class="tree-div" style="width: 300px;"> <mat-tree [dataSource]="dataSource" [treeControl]="treeControl" class="example-tree"> <!-- Leaf Node Template --> <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle> <li class="mat-tree-node"> <button mat-icon-button disabled></button> <!-- Add click event to pass the current node --> <span (click)="onNodeClick(node)">{{node.name}}</span> </li> </mat-tree-node> <!-- Expandable Node Template --> <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 class="mat-icon-rtl-mirror"> {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}} </mat-icon> </button> <!-- Add click event here too --> <span (click)="onNodeClick(node)">{{node.name}}</span> </div> <ul [class.example-tree-invisible]="!treeControl.isExpanded(node)"> <ng-container matTreeNodeOutlet></ng-container> </ul> </li> </mat-nested-tree-node> </mat-tree> </div> <div style="flex: 1;"> <!-- Display selected node name --> <div *ngIf="selectedNode" style="margin-bottom: 1rem;"> <strong>Selected Node:</strong> {{selectedNode.name}} </div> <!-- Mat-table to show child nodes --> <mat-table [dataSource]="tableDataSource" *ngIf="selectedNode" class="mat-elevation-z8"> <!-- Name Column Definition --> <ng-container matColumnDef="name"> <mat-header-cell *matHeaderCellDef> Child Node Name </mat-header-cell> <mat-cell *matCellDef="let child"> {{child.name}} </mat-cell> </ng-container> <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row> <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row> </mat-table> <!-- No children message --> <div *ngIf="selectedNode && (!selectedNode.children || selectedNode.children.length === 0)" style="padding: 2rem; text-align: center; color: #666;"> This node has no child nodes. </div> <!-- No selection message --> <div *ngIf="!selectedNode" style="padding: 2rem; text-align: center; color: #666;"> Select a node from the tree to view its children. </div> </div> </div>
Step 3: Optional Styling (app.component.css)
Add these styles to clean up the tree and table display:
.example-tree-invisible { display: none; } .example-tree ul, .example-tree li { margin: 0; list-style-type: none; } .mat-tree-node { cursor: pointer; } .mat-tree-node span:hover { text-decoration: underline; } .mat-table { width: 100%; }
Key Fixes & Explanations:
- Selected Node Tracking: We added a
selectedNodeproperty to store the clicked node, which lets us access its data in the right panel. - Node Click Handler: The
onNodeClickmethod updates both the selected node reference and the table's data source with the node's children. - Template Context Fix: Your original code tried to access
nodeoutside the tree node template (where it doesn't exist). Now we useselectedNodeto display the name and drive the table. - Table Integration: The Mat-table is bound to
tableDataSource, which refreshes every time a node is clicked.
Now when you click any node in the tree, the right panel will show the node's name and a table of its child nodes (or a message if there are no children).
内容的提问来源于stack exchange,提问作者Dharam1986

