Angular动态FormArray选中行填充输入框时新增行值重复问题
问题现象
在Angular项目中基于响应式表单FormArray实现支持动态增删的表格行表单时,存在如下异常:从模态框内的mat-table列表选中值填充输入框时,新增的第二行会自动带出与第一行完全相同的值;但手动输入值时功能正常,仅新增行初始加载阶段无该异常。
可选值列表存放于模态框内的mat-table组件中。
问题复现代码
HTML模板
<form [formGroup]="Form"> <div formArrayName="ItemRec"> <table> <thead> <tr> <th>FORM</th> </tr> </thead> <tbody> <tr *ngFor="let ItemRec of ItemRec.controls; let i = index;" [formGroupName]="i"> <td (click)="removeRow(i)" style="width:100px" align="center"> <i class="fa fa-trash fa-2x"></i></td> <td> <input style="width:200px" class="form-control" formControlName="dr" ngModel={{transactionCode}}> </td> </tr> </tbody> </table> </form>
TS逻辑
this.Form = this.fb.group({ Id:['0'], ItemRec: this.fb.array([this.CreateItemRec()]) }) } CreateItemRec(): FormGroup { return this.fb.group({ id:[0], dr: new FormControl('',Validators.required), }) } get ItemRec(): FormArray { return <FormArray>this.Form.get('ItemRec') as FormArray } addRow(): void { this.ItemRec?.push(this.CreateItemRec());
根因分析
- 核心问题是响应式表单与模板驱动表单写法违规混用:输入框已经绑定了响应式表单指令
formControlName="dr",又额外添加了ngModel={{transactionCode}}的模板驱动绑定,属于Angular官方明确不推荐的写法,极易引发值同步异常。 transactionCode是组件级的全局单一变量,不属于FormArray下某一行独立FormGroup的独有字段,所有行的输入框都会同步绑定这同一个变量。- 从模态框选值时如果直接修改全局
transactionCode,所有未被手动输入过值的新增行,因为dr控件初始值为空,会直接拉取这个全局变量的值渲染,就出现了新增行自动带出第一行选中值的串值问题;手动输入时,输入操作直接修改了对应行FormControl的自有值,渲染优先级高于全局ngModel的绑定值,所以不会串值,看起来功能正常。
修复方案
- 移除输入框上多余的
ngModel绑定,全程使用响应式表单API做值更新,不要混用两种表单模式,修复后的输入框代码如下:
<input style="width:200px" class="form-control" formControlName="dr">
- 从模态框选中值后,不要给全局
transactionCode赋值,而是定位到当前操作行对应的dr控件,调用响应式表单的setValue/patchValue方法完成赋值,示例逻辑:
// 假设当前操作行为第i行,模态框选中的目标值为selectedValue this.ItemRec.at(i).get('dr')?.setValue(selectedValue);
- 现有
CreateItemRec、addRow的写法符合要求,每次新增行都会生成全新的FormGroup实例,不会出现实例复用导致的值串流问题,无需调整。
内容的提问来源于stack exchange,提问作者Yan
相关产品推荐
相关产品推荐

