Angular动态网格行内动态新增表单元素的valueChanges仅影响最后一行问题
问题根因
代码的核心问题是循环中复用了类全局的this.formGroup变量,每次循环迭代都会覆盖这个变量的值,而valueChanges的订阅回调是异步触发的,闭包引用的this.formGroup最终会指向循环结束后的最后一行表单实例,所以所有行的下拉变化都只会操作最后一行的输入框。
修复方案
不需要用全局变量存储当前行表单,直接在循环作用域内声明局部变量存储每行的表单实例,确保每个订阅回调绑定的是当前迭代的表单对象即可,修改后代码如下:
public editRows(grid: GridComponent) { let currentRow = 0; const rows = grid.data; const itemsFormArray = this.formGroups.get('items') as FormArray; // 建议用rows.length代替硬编码6,避免数据量不足时报错 for (let i = 0; i < rows.length; i++) { // 声明局部变量存储当前行表单,不要用this.formGroup全局变量 const rowForm = this.createFormGroup(rows[i]); itemsFormArray.push(rowForm); grid.editRow(currentRow, rowForm, {skipFocus: true}); currentRow++; // 初始化禁用状态 if(rowForm.controls.dataType.value !== 'Value List') { rowForm.get('inputValues').disable(); } // 订阅当前行的下拉变化,闭包绑定的是当前循环的rowForm实例,不会被后续迭代覆盖 rowForm.get('dataType').valueChanges.subscribe(selectedValue => { if(selectedValue !== 'Value List') { rowForm.get('inputValues').disable(); } else { rowForm.get('inputValues').enable(); } }); } }
额外优化建议
- 每次进入编辑模式前先清空
itemsFormArray的旧控件,避免重复累加表单实例 - 组件销毁时要取消所有
valueChanges的订阅,避免内存泄漏,可以用一个订阅数组存储所有订阅,在ngOnDestroy钩子中统一取消:
private subscriptions: Subscription[] = []; // 订阅时将实例push到数组 this.subscriptions.push(rowForm.get('dataType').valueChanges.subscribe(...)); // 组件销毁时统一取消订阅 ngOnDestroy() { this.subscriptions.forEach(sub => sub.unsubscribe()); }
内容的提问来源于stack exchange,提问作者vamsi
相关产品推荐
相关产品推荐

