Mat Dialog内嵌Mat Table点击addRow时行取值相同问题
问题复现流程
- 页面初始加载内置Mat Table,展示状态正常

- 触发交互打开Mat Dialog弹窗,弹窗内加载带数据列表的Mat Table,初始加载状态正常

- 点击
addRow按钮新增表格行时,新增行直接复用已有行取值,出现全表行数据联动异常:第一行已填/已选值无法保留,第二行选值会同步覆盖首行数据,各行无法独立维护数据
核心诉求:新增行时保留已有行的填写内容,支持各行独立维护数据,解决数据联动覆盖问题。
问题原因
核心是对象引用共用:
- 新增行时直接把已有行的对象引用推入数据源数组,多行绑定同一个内存地址的对象,任意行修改字段会同步影响所有绑定该对象的行
- 如果用响应式表单实现行编辑,新增行时直接复用已有行的FormGroup/FormControl实例,没有新建独立控件,也会导致数据联动
- 表格未配置
trackBy时,Angular DOM节点复用错误也可能偶发控件状态串改
修复方案
1. 新增行时初始化独立数据对象
禁止直接复用已有行对象引用,新行必须生成独立对象,嵌套引用类型做深拷贝:
// 错误写法:直接push已有行对象,导致引用共用 addRow() { this.dataSource.data.push(this.dataSource.data.at(-1)) } // 正确写法:新建独立对象 addRow() { const newRow = { id: Date.now(), // 生成唯一行标识 selectVal: null, inputVal: '', // 有嵌套对象时用深拷贝,例: // extend: JSON.parse(JSON.stringify(lastRow.extend)) } this.dataSource.data = [...this.dataSource.data, newRow] }
2. 表单场景新建独立控件实例
用响应式表单FormArray实现行编辑时,新增行必须生成全新的FormGroup实例,禁止直接推入已有FormGroup:
// 抽离单行表单初始化方法 initRowForm(defaultVal?: any): FormGroup { return this.fb.group({ selectVal: [defaultVal?.selectVal || null], inputVal: [defaultVal?.inputVal || ''] }) } addFormRow() { const rowArr = this.form.get('rowList') as FormArray // 每次新增都生成新的FormGroup实例 rowArr.push(this.initRowForm()) }
3. 配置表格trackBy函数
给Mat Table配置trackBy,用行唯一标识追踪行状态,避免DOM错误复用:
<table mat-table [dataSource]="dataSource" [trackBy]="rowTrackBy"> <!-- 列定义省略 --> </table>
rowTrackBy(index: number, row: any) { // 优先用行唯一ID,没有就用索引 return row.id || index }
内容的提问来源于stack exchange,提问作者Yan
相关产品推荐
相关产品推荐

