Angular Material Table实现全部行展开功能求助
解决Angular Material Table展开全部子行的问题
嘿,作为Angular新手碰到这个需求太正常啦!我帮你基于你现有的示例改造,实现展开全部/收起全部的功能,同时保留原有的单行展开/收起能力~
整体思路
原来的示例是通过单个expandedElement变量控制单行展开,现在我们需要:
- 新增全局展开状态变量,同时维护一个集合记录独立展开的行
- 修改表格行的展开条件,兼顾全局状态和单行独立控制
- 调整自定义指令,支持接收外部传入的展开状态
步骤1:修改组件的状态管理
在你的表格组件(比如table.component.ts)里,替换原来的expandedElement变量,新增以下状态:
// 全局展开开关 expandAll = false; // 记录独立展开的行(当全局未展开时生效) expandedElements = new Set<any>();
然后添加展开/收起全部的方法:
// 展开所有行 expandAllRows() { this.expandAll = true; // 把所有数据加入集合,确保全局展开时所有行都处于展开状态 this.dataSource.data.forEach(item => this.expandedElements.add(item)); } // 收起所有行 collapseAllRows() { this.expandAll = false; this.expandedElements.clear(); } // 切换单行展开状态 toggleRow(row: any) { if (this.expandAll) { // 如果是全局展开状态,点击行就单独收起它 this.expandedElements.delete(row); // 如果所有行都被单独收起,自动关闭全局开关 if (this.expandedElements.size === 0) { this.expandAll = false; } } else { // 非全局状态时,切换该行的展开状态 if (this.expandedElements.has(row)) { this.expandedElements.delete(row); } else { this.expandedElements.add(row); } } }
步骤2:修改模板(HTML)
首先添加展开/收起全部的按钮:
<div class="table-controls"> <button mat-button (click)="expandAllRows()">展开全部</button> <button mat-button (click)="collapseAllRows()">收起全部</button> </div>
然后修改表格行的点击事件和展开条件,把原来绑定expandedElement的地方改成我们的新逻辑:
<!-- 主行 --> <tr mat-row *matRowDef="let row; columns: displayedColumns;" [cdkDetailRow]="row" [cdkDetailRowTpl]="tpl" [isExpanded]="expandAll || expandedElements.has(row)" (click)="toggleRow(row)"> </tr> <!-- 子行模板(保持原来的即可) --> <ng-template #tpl let-row> <tr mat-row> <td colspan="100"> <!-- 你的子行内容 --> {{ row | json }} </td> </tr> </ng-template>
步骤3:调整自定义指令(cdk-detail-row.directive.ts)
原来的指令是监听expandedElement,现在我们改成接收isExpanded输入,这样组件可以灵活控制每一行的状态:
import { Directive, Input, TemplateRef, ViewContainerRef, OnInit, OnDestroy } from '@angular/core'; @Directive({ selector: '[cdkDetailRow]' }) export class CustomCdkDetailRowDirective implements OnInit, OnDestroy { @Input() cdkDetailRow: any; @Input() cdkDetailRowTpl: TemplateRef<any>; @Input() set isExpanded(value: boolean) { this.toggleRow(value); } private rowExpanded = false; constructor( private viewContainerRef: ViewContainerRef, private templateRef: TemplateRef<any> ) {} ngOnInit() {} ngOnDestroy() { this.viewContainerRef.clear(); } private toggleRow(expanded: boolean) { if (expanded && !this.rowExpanded) { this.viewContainerRef.createEmbeddedView(this.cdkDetailRowTpl, { $implicit: this.cdkDetailRow }); this.rowExpanded = true; } else if (!expanded && this.rowExpanded) { this.viewContainerRef.clear(); this.rowExpanded = false; } } }
功能说明
- 点击「展开全部」:所有子行都会展开,此时点击任意主行可以单独收起该行
- 点击「收起全部」:所有子行都会收起,回到初始状态
- 非全局展开状态时,点击主行可以单独展开/收起该行
- 如果全局展开后,所有行都被单独收起,全局开关会自动关闭
这样就完美兼容了原有功能和新增的展开全部需求啦!
内容的提问来源于stack exchange,提问作者user2894816
相关产品推荐
相关产品推荐

