Angular响应式表单:子组件初始化Infos FormArray的最佳方式
问题描述
我正在使用Angular响应式表单,现有一个接收Detail类型数组的组件,在该组件中遍历数组项并创建新的FormGroup。相关代码如下:
export interface Detail { note : string; infos : string[] } @Input() details: Detail[]; ngOnInit(): void { const formArray = <UntypedFormArray>this.rootFormGroup.form.controls[this.formArrayName] as FormArray; formArray.clear({emitEvent: false}); for (const detail of this.details) { formArray.push( new UntypedFormGroup({ note: new UntypedFormControl(detail.note, [Validators.required]), infos: new UntypedFormArray([]), }) ); } }
<ng-container [formArrayName]="formArrayName"> <span *ngFor="let option of formArray.controls; let i = index" [formGroupName]="i"> {{option.note}} <child-info-container infos-list="???"> </child-info-container> </ng-container>
当前代码运行正常,但我希望在子组件中初始化infos FormArray。在遍历FormArray控件的HTML结构中,最佳的访问方式是什么?
解决方案
要实现子组件初始化infos对应的FormArray,核心是把当前FormGroup中的infos控件准确传递给子组件,具体操作如下:
- 父组件HTML中传递目标FormArray
在*ngFor的循环上下文里,option是当前的FormGroup实例,你可以通过option.get('infos')直接获取到对应的UntypedFormArray,同时把原始初始化数据details[i].infos也传给子组件,方便后续填充:
<ng-container [formArrayName]="formArrayName"> <span *ngFor="let option of formArray.controls; let i = index" [formGroupName]="i"> {{option.get('note')?.value}} <child-info-container [infosList]="option.get('infos') as UntypedFormArray" [initialInfos]="details[i].infos"> </child-info-container> </span> </ng-container>
注意:模板中获取note的值要使用option.get('note')?.value,而非option.note——因为option是FormGroup对象,本身没有note属性。
- 子组件接收并初始化FormArray
子组件定义对应的输入属性,在ngOnInit生命周期中用原始数据填充FormArray:
import { Component, Input, OnInit } from '@angular/core'; import { UntypedFormArray, UntypedFormControl } from '@angular/forms'; @Component({ selector: 'child-info-container', // 子组件模板内容 }) export class ChildInfoContainerComponent implements OnInit { @Input() infosList!: UntypedFormArray; @Input() initialInfos!: string[]; ngOnInit(): void { // 先清空避免重复初始化 this.infosList.clear({emitEvent: false}); // 遍历原始数据创建FormControl并添加到数组 this.initialInfos.forEach(info => { this.infosList.push(new UntypedFormControl(info)); }); } }
- 可选优化:父组件直接初始化FormArray
如果不需要子组件承担初始化逻辑,也可以在父组件创建FormGroup时直接填充infos数组,代码更简洁:
for (const detail of this.details) { // 直接用原始infos数组生成FormArray const infosArray = new UntypedFormArray( detail.infos.map(info => new UntypedFormControl(info)) ); formArray.push( new UntypedFormGroup({ note: new UntypedFormControl(detail.note, [Validators.required]), infos: infosArray, }) ); }
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

