You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular Material Table实现全部行展开功能求助

解决Angular Material Table展开全部子行的问题

嘿,作为Angular新手碰到这个需求太正常啦!我帮你基于你现有的示例改造,实现展开全部/收起全部的功能,同时保留原有的单行展开/收起能力~

整体思路

原来的示例是通过单个expandedElement变量控制单行展开,现在我们需要:

  1. 新增全局展开状态变量,同时维护一个集合记录独立展开的行
  2. 修改表格行的展开条件,兼顾全局状态和单行独立控制
  3. 调整自定义指令,支持接收外部传入的展开状态

步骤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;
    }
  }
}

功能说明

  1. 点击「展开全部」:所有子行都会展开,此时点击任意主行可以单独收起该行
  2. 点击「收起全部」:所有子行都会收起,回到初始状态
  3. 非全局展开状态时,点击主行可以单独展开/收起该行
  4. 如果全局展开后,所有行都被单独收起,全局开关会自动关闭

这样就完美兼容了原有功能和新增的展开全部需求啦!

内容的提问来源于stack exchange,提问作者user2894816

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:30:58