Angular中使用FormArray动态控制FormGroup数量时,单个控件值同步更新所有FormGroup的问题排查
嘿,我一眼就看到你踩了个常见的JavaScript数组坑!问题根本不是模板里的[formGroup]="formList.controls[i]",而是你初始化FormArray的方式错了。
错误原因
你在getFormControls方法里用了Array.fill():
myArray.fill(this.fb.group({ length: [''], width: [''], height: [''] }));
fill()方法的特性是:它会把同一个对象实例填充到数组的每一个位置。也就是说,你的formList数组里的5个元素,全都是指向同一个FormGroup对象的引用!不管你修改哪个索引对应的输入框,本质上都是在修改同一个FormGroup,所以所有组的值会同步变化,这就导致了你看到的所有FormGroup值一模一样的情况。
修复方案
你需要为数组的每个位置创建独立的FormGroup实例,而不是复用同一个。这里有两种简单的实现方式:
方式1:用Array.from()生成独立实例
修改getFormControls方法:
getFormControls(numberOfFormGroups: number) { // 为每个元素创建新的FormGroup return Array.from({ length: numberOfFormGroups }, () => this.fb.group({ length: [''], width: [''], height: [''] }) ); }
方式2:用for循环逐个添加
如果觉得Array.from()不够直观,也可以用传统的循环:
getFormControls(numberOfFormGroups: number) { const myArray = []; for (let i = 0; i < numberOfFormGroups; i++) { // 每次循环都创建新的FormGroup myArray.push(this.fb.group({ length: [''], width: [''], height: [''] })); } return myArray; }
这两种方式的核心都是:每次调用this.fb.group()都会生成一个全新的FormGroup对象,数组里的每个元素都是独立的,修改其中一个不会影响其他组的值。
模板优化建议
另外,你已经定义了unitList这个getter来获取FormArray,完全可以在模板里直接用它,让代码更简洁:
<div formArrayName="formList"> <div *ngFor="let unitForm of unitList.controls; let i = index" [formGroup]="unitForm"> <pre>{{unitForm.value | json}}</pre> <pre>i = {{i}}</pre> <mat-form-field> <input matInput formControlName="length" /> </mat-form-field> <mat-form-field> <input matInput formControlName="width" /> </mat-form-field> <mat-form-field> <input matInput formControlName="height" /> </mat-form-field> </div> </div>
直接用unitForm代替重复的formList.controls[i],代码可读性会更好。
总结
本质问题就是JavaScript的引用类型特性——Array.fill()复用了同一个FormGroup实例,导致所有数组元素共享同一个引用。只要确保每个数组元素都是独立的FormGroup实例,就能解决所有组同步更新的问题啦!
内容的提问来源于stack exchange,提问作者gh0st

