Mat-Dialog回传数据时afterClosed内FormArray patchValue不生效问题
问题根因
- 弹窗生命周期钩子写法错误:将
ngOnInit写为OnInit,Angular无法识别执行初始化逻辑,表单初始赋值、valueChanges订阅都不会生效。 - 弹窗回传数据格式错误:
save()方法里用[this.data.qty]把qty包成了单元素数组回传,父组件拿到的result是数组而非预期的数值/对象,循环、取值逻辑全部失效。 - 父组件FormArray的子项结构不匹配:
CreatesetItem()生成的FormGroup仅包含ListItem控件,不存在qty字段,调用patchValue({ qty: xxx })时找不到对应控件,自然无法更新渲染。 - 重复操作残留脏数据:每次打开弹窗回调里直接往
setItem里push新项,没有清空之前的旧控件,多次操作会产生冗余表单项。 - 赋值逻辑错误:就算回传格式正确,
result.qty的取值也和回传结构不匹配,拿不到有效值;且setValue本身无返回值,原代码中将其返回值赋给this.data属于无效写法。
修复方案
1. 修正弹窗组件逻辑
// 弹窗组件代码 ngOnInit(): void { this.fg = this.fb.group({ id: [], qty: [], displayArray: this.fb.array([this.CreateItem()]), }); this.fg.get('qty').valueChanges.subscribe((res) => { // 增加边界判断,避免非法值报错 if (typeof res !== 'number' || res < 0) return; // 数量减少时移除多余表单项,不要只加不减 while (this.displayArray.length > res) { this.displayArray.removeAt(this.displayArray.length - 1); } for (let i = this.displayArray.length; i < res; i++) { this.displayArray.push(this.CreateItem()); } }); // setValue无返回值,直接调用即可 this.fg.get('qty').setValue(this.data.qty); } CreateItem(): FormGroup { return this.fb.group({ MoreItem: [''], }); } get displayArray(): FormArray { return this.fg.get('displayArray') as FormArray; } save() { // 回传结构化对象,不要包无意义的数组 this.dialogRef.close({ qty: this.fg.value.qty, displayItems: this.fg.value.displayArray }); }
2. 修正父组件FormArray逻辑
// 父组件代码 CreatesetItem(): FormGroup { // 补全需要的表单字段,和后续赋值的属性一一对应 return this.fb.group({ ListItem: [''], qty: [] // 原代码漏了该控件,是patchValue不生效的核心原因之一 }); } get setItem(): FormArray { return this.fg.get('setItem') as FormArray; } get Info(): FormArray { return this.fg.get('Info') as FormArray; } openAlertDialog(index: number) { const dialogRef = this.dialog.open(AlertDialogComponent, { data: { qty: this.fg.value.Info[index].qty, name: this.fg.value.Info[index].name, }, }); dialogRef.afterClosed().subscribe((result) => { // 用户点遮罩、ESC取消弹窗时result为undefined,直接终止逻辑 if (!result) return; // 先清空旧的表单项,避免重复堆积 while (this.setItem.length) { this.setItem.removeAt(0); } // 按回传的数量生成新表单项 for (let i = 0; i < result.qty; i++) { const newItem = this.CreatesetItem(); newItem.patchValue({ qty: result.qty, ListItem: result.displayItems[i]?.MoreItem || '' }) this.setItem.push(newItem); } // 同步更新Info数组对应项的qty值 this.Info.at(index).patchValue({ qty: result.qty }); }); }
极端场景兼容
如果组件使用OnPush变更检测策略,赋值后视图未正常刷新,可注入ChangeDetectorRef,在赋值逻辑末尾调用this.cdr.markForCheck()手动触发视图更新即可。
内容的提问来源于stack exchange,提问作者Yan
相关产品推荐
相关产品推荐

