如何在TS文件中编程式展开Mat Table表格中的mat-rows行?
多级嵌套Mat Table通过TS代码控制行展开实现方案
你当前使用的三级可展开Mat Table本质是通过行数据对应的布尔状态字段控制展开/收起状态,通过TS代码控制只需要修改对应行的状态字段再触发表格重渲染即可,具体实现步骤如下:
步骤1:给各层级数据定义展开状态字段
首先确保你的数据源结构中,每个层级的行数据都有对应的独立展开状态标记,示例结构参考:
// 一级行数据结构 export interface Level1Item { id: number; name: string; isExpanded: boolean; // 控制一级行展开状态 level2Items: Level2Item[]; } // 二级行数据结构 export interface Level2Item { id: number; name: string; parentId: number; isSecondLevelExpanded: boolean; // 控制二级行展开状态 level3Items: Level3Item[]; } // 三级行数据结构 export interface Level3Item { id: number; name: string; parentId: number; isThirdLevelExpanded: boolean; // 控制三级行展开状态 }
步骤2:封装行展开控制方法
在TS文件中封装按条件匹配目标行、修改展开状态的方法,支持按ID、名称等业务规则定位行:
import { MatTableDataSource } from '@angular/material/table'; // 初始化的一级表格数据源 dataSource = new MatTableDataSource<Level1Item>(); /** * 展开指定一级行 * @param targetId 目标一级行ID * @param exclusive 是否排他展开(是则关闭其他同级已展开行,否则保留其他展开状态) */ expandLevel1Row(targetId: number, exclusive: boolean = false) { this.dataSource.data.forEach(item => { if (exclusive) { item.isExpanded = item.id === targetId; } else if (item.id === targetId) { item.isExpanded = true; } }); // 触发表格重渲染 this.dataSource._updateChangeSubscription(); } /** * 展开指定二级行,会自动展开对应的父级一级行 * @param parentLevel1Id 父级一级行ID * @param targetLevel2Id 目标二级行ID * @param exclusive 是否排他展开 */ expandLevel2Row(parentLevel1Id: number, targetLevel2Id: number, exclusive: boolean = false) { const parentLevel1 = this.dataSource.data.find(item => item.id === parentLevel1Id); if (!parentLevel1) return; // 先展开父级一级行 parentLevel1.isExpanded = true; parentLevel1.level2Items.forEach(level2Item => { if (exclusive) { level2Item.isSecondLevelExpanded = level2Item.id === targetLevel2Id; } else if (level2Item.id === targetLevel2Id) { level2Item.isSecondLevelExpanded = true; } }); this.dataSource._updateChangeSubscription(); } /** * 展开指定三级行,会自动展开对应的一级、二级父级行 * @param parentLevel1Id 父级一级行ID * @param parentLevel2Id 父级二级行ID * @param targetLevel3Id 目标三级行ID * @param exclusive 是否排他展开 */ expandLevel3Row(parentLevel1Id: number, parentLevel2Id: number, targetLevel3Id: number, exclusive: boolean = false) { const parentLevel1 = this.dataSource.data.find(item => item.id === parentLevel1Id); if (!parentLevel1) return; parentLevel1.isExpanded = true; const parentLevel2 = parentLevel1.level2Items.find(item => item.id === parentLevel2Id); if (!parentLevel2) return; parentLevel2.isSecondLevelExpanded = true; parentLevel2.level3Items.forEach(level3Item => { if (exclusive) { level3Item.isThirdLevelExpanded = level3Item.id === targetLevel3Id; } else if (level3Item.id === targetLevel3Id) { level3Item.isThirdLevelExpanded = true; } }); this.dataSource._updateChangeSubscription(); }
步骤3:对齐HTML层状态绑定
确保你的HTML模板中,各层级展开的判定条件和TS中修改的状态字段完全对应,示例参考:
<!-- 一级展开内容判定 --> <div class="level1-expand-content" *ngIf="element.isExpanded"> <!-- 二级表格内容 --> <div class="level2-expand-content" *ngIf="subElement.isSecondLevelExpanded"> <!-- 三级表格内容 --> <div class="level3-expand-content" *ngIf="thirdElement.isThirdLevelExpanded"> 三级展开内容 </div> </div> </div>
常见注意事项
- 如果你的表格是展开时才动态加载子级数据,需要先触发子级数据加载逻辑,再修改对应行的展开状态
- 如果你的数据源使用
BehaviorSubject维护,替换_updateChangeSubscription()调用为next方法更新数据源即可生效 - 收起行的逻辑和展开逻辑一致,只需要把对应状态字段设为
false即可
内容的提问来源于stack exchange,提问作者Sunny Srivastava
相关产品推荐
相关产品推荐

