如何在Angular中创建行列标题一致且带绑定复选框的矩阵表格?
问题修复与实现方案
问题分析
- 复选框全部联动:当前
mat-table的数据源weightMatrix是单元格级别的对象数组,每一行的所有复选框都绑定到同一个element.value,导致选中一个时整行的复选框同步变化。 - 首列行标题不匹配:HTML模板中尝试显示
element.row,但TableMatrix对象中没有row属性,且行数据的生成逻辑错误,未正确关联行标题。
修复方案
1. 重构数据结构
定义行数据类型,每一行对应一个标题,以及各列的复选框状态:
// 行数据结构:包含行标题和各列的选中状态映射 interface TableRow { rowTitle: string; rowIndex: number; columnValues: { [key: string]: boolean }; }
2. 修正HTML模板
调整表格列定义,首列显示行标题,各列绑定对应列的独立选中状态:
<table mat-table [dataSource]="tableRows" class="mat-elevation-z8"> <!-- 首列:行标题列 --> <ng-container matColumnDef="rowTitle"> <th mat-header-cell *matHeaderCellDef>#</th> <td mat-cell *matCellDef="let row"> {{row.rowTitle}} </td> </ng-container> <!-- 动态列:对应每个自定义标题 --> <ng-container *ngFor="let column of weightingComponents" [matColumnDef]="column.name"> <th mat-header-cell *matHeaderCellDef> {{column.name}} </th> <td mat-cell *matCellDef="let row"> <input type="checkbox" [(ngModel)]="row.columnValues[column.name]"> </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table>
3. 修改组件TS逻辑
重新初始化行数据,确保每个单元格选中状态独立,同时正确设置显示列:
import { Component, Input, OnInit } from '@angular/core'; import { WeightingComponent } from '../weighting/weighting.component'; // 行数据接口 interface TableRow { rowTitle: string; rowIndex: number; columnValues: { [key: string]: boolean }; } const SET_RULES_POC: string[] = ['Test1', 'Test2', 'Test3']; @Component({ selector: 'app-table-component', templateUrl: './table-component.html', styleUrls: ['./table-component.scss'], }) export class TableComponent implements OnInit { @Input() weightingComponents: WeightingComponent[] = []; tableRows: TableRow[] = []; displayedColumns: string[] = []; ngOnInit(): void { // 初始化列标题组件 for (let i = 0; i < SET_RULES_POC.length; i++) { this.weightingComponents.push(new WeightingComponent(SET_RULES_POC[i], i)); } // 生成每行数据,为每个列初始化选中状态(默认false) this.tableRows = this.weightingComponents.map((component, rowIndex) => { const columnValues: { [key: string]: boolean } = {}; this.weightingComponents.forEach(col => { columnValues[col.name] = false; // 可选:如需对角线默认选中,可添加判断 // columnValues[col.name] = col.position === rowIndex; }); return { rowTitle: component.name, rowIndex: rowIndex, columnValues: columnValues }; }); // 设置显示列:首列+所有自定义列标题 this.displayedColumns = ['rowTitle', ...this.weightingComponents.map(col => col.name)]; } // 获取指定单元格的选中状态 getCellValue(rowIndex: number, columnName: string): boolean { return this.tableRows[rowIndex]?.columnValues[columnName] ?? false; } // 打印所有单元格状态 logAllValues(): void { this.tableRows.forEach(row => { console.log(`行 ${row.rowTitle}:`, row.columnValues); }); } }
4. 关键优化说明
- 复选框联动修复:每个单元格绑定到
row.columnValues[column.name],每个列对应独立的属性,彻底解决联动问题。 - 首列标题修复:首列直接显示
row.rowTitle,与行标题完全匹配。 - 最佳实践调整:使用
TableRow封装行数据,符合Angular Material Table的数据源设计;避免修改全局常量SET_RULES_POC(原代码中unshift('#')会污染全局值)。
内容的提问来源于stack exchange,提问作者SCramphorn
相关产品推荐
相关产品推荐

