Angular表单中如何实现深层嵌套数组的数据绑定?
Angular嵌套FormArray表单绑定解决方案
问题分析
当前已实现外层list数组的添加功能,但无法访问内层list_items数组进行数据绑定,需修正模板与组件逻辑,传递正确的表单控件引用给子组件。
代码修正步骤
1. 父组件模板(Parent-comp.html)修正
移除重复的formControlName,绑定内层list_items数组,循环渲染子组件并传递对应FormGroup:
<p>form-comp works!</p> <div class="form-container"> <form (ngSubmit)="submit()" [formGroup]="myForm"> <h1>User Registration</h1> <div class="form-group"> <label for="firstname"></label> <input type="text" placeholder="First Name" formControlName="name" /> <input type="text" placeholder="Surname" formControlName="email" /> <br /> <div formArrayName="list"> <ng-container *ngFor="let myList of listArray.controls; index as i"> <div [formGroupName]="i"> <input type="text" placeholder="List Title" formControlName="list_title" /> <br /> <!-- 绑定内层list_items数组 --> <div formArrayName="list_items"> <ng-container *ngFor="let item of getListItems(i).controls; index as j"> <div [formGroupName]="j"> <app-products [childForm]="item"></app-products> </div> </ng-container> <!-- 添加单个列表项按钮 --> <button type="button" (click)="addListItem(i)">Add List Item</button> </div> </div> <hr> </ng-container> <button type="button" (click)="addList()">Add List</button> </div> <button type="submit">Submit</button> </div> <br /> <div class="form-check"> {{ myForm.value | json }} <br /> {{ myForm.valid | json }} </div> </form> </div>
2. 父组件代码(Parent-comp.ts)修正
添加获取内层list_items数组的方法,以及单个列表项的添加方法:
import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, FormArray, FormControl, Validators } from '@angular/forms'; import { ProductsComponent } from './products.component'; export class FormCompComponent implements OnInit { myForm!: FormGroup; constructor (private fb : FormBuilder) {} ngOnInit(): void { this.myForm = this.fb.group({ name: ['', Validators.required], email: ['', Validators.required], list: this.fb.array([this.initListFormGroup()]), }); } addList() { this.listArray.push(this.initListFormGroup()); } // 获取外层list数组 get listArray() { return this.myForm.get('list') as FormArray; } // 获取指定list项的内层list_items数组 getListItems(listIndex: number): FormArray { return this.listArray.at(listIndex).get('list_items') as FormArray; } // 给指定list添加单个列表项 addListItem(listIndex: number) { this.getListItems(listIndex).push(ProductsComponent.addListItem()); } initListFormGroup() { return this.fb.group({ list_title: ['', Validators.required], list_items: this.fb.array([ ProductsComponent.addListItem()]) }); } submit() { console.log(this.myForm.value); } }
3. 子组件代码(ProductsComponent)修正
修正addListItem方法的语法错误,调整模板匹配数据结构:
子组件模板(Child-comp.html):
<div [formGroup]="childForm"> <input type="text" placeholder="List Item 1" formControlName="list_item_1" /> <input type="text" placeholder="List Item 2" formControlName="list_item_2" /> </div>
子组件代码:
import { Component, Input } from '@angular/core'; import { FormGroup, FormControl } from '@angular/forms'; @Component({ selector: 'app-products', templateUrl: './products.component.html', }) export class ProductsComponent { @Input() public childForm!: FormGroup; constructor() {} static addListItem(): FormGroup { return new FormGroup({ list_item_1: new FormControl(''), list_item_2: new FormControl(''), }); } }
关键说明
- 父组件通过
getListItems方法定位指定外层list项的内层数组,实现对内层控件的访问 - 内层数组渲染需在
formArrayName="list_items"容器内,通过[formGroupName]="j"绑定单个列表项的FormGroup - 子组件通过
@Input()接收单个列表项的FormGroup,完成数据双向绑定 - 修复了原代码中重复
formControlName、错误初始化FormGroup等语法问题
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

