Angular动态嵌套FormArray无法正常工作问题求助
我正在学习Angular,想要实现一个可添加/删除的书籍数组,每本书对应一个同样可添加/删除的作者数组,但一直遇到错误:Cannot find control with path: 'books -> 0 -> authors -> 0'
TS代码
import { Component, OnInit } from '@angular/core'; import {FormArray, FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms'; import {STEPPER_GLOBAL_OPTIONS} from '@angular/cdk/stepper'; /** * @title Stepper that displays errors in the steps */ @Component({ selector: 'app-home', templateUrl: 'home.component.html', styleUrls: ['home.component.scss'], providers: [ { provide: STEPPER_GLOBAL_OPTIONS, useValue: {showError: true}, }, ], }) export class HomeComponent implements OnInit { bookForm: FormGroup; constructor(private fb: FormBuilder) { this.bookForm = this.fb.group({ books: this.fb.array([]) // Create an empty FormArray for books }); } ngOnInit(): void { this.createBook() } get books() { return this.bookForm.get('books') as FormArray; } addBook() { this.books.push(this.createBook()); } removeBook(index: number) { this.books.removeAt(index); } createBook() { return this.fb.group({ title: ['', Validators.required], authors: this.fb.array([this.createAuthor()]) // Initialize with an empty author control }); } createAuthor() { return this.fb.control('', Validators.required); } getAuthors(bookIndex: number) { return this.books.at(bookIndex).get('authors') as FormArray; } addAuthor(bookIndex: number) { const book = this.books.at(bookIndex) as FormGroup; const authors = book.get('authors') as FormArray; authors.push(this.createAuthor()); } removeAuthor(bookIndex: number, authorIndex: number) { const book = this.books.at(bookIndex) as FormGroup; const authors = book.get('authors') as FormArray; authors.removeAt(authorIndex); } onSubmit() { if (this.bookForm.valid) { // Handle form submission console.log(this.bookForm.value); } } }
HTML代码
<form [formGroup]="bookForm" (ngSubmit)="onSubmit()"> <div formArrayName="books"> <div *ngFor="let book of books.controls; let bookIndex = index"> <div [formGroupName]="bookIndex"> <div> <label> Book Title: <input formControlName="title"> </label> <button type="button" (click)="removeBook(bookIndex)">Remove Book</button> </div> <div formArrayName="authors"> <div *ngFor="let author of getAuthors(bookIndex).controls; let authorIndex = index"> <div [formGroupName]="authorIndex"> <label> Author: <input formControlName="authorName"> </label> <button type="button" (click)="removeAuthor(bookIndex, authorIndex)">Remove Author</button> </div> </div> <button type="button" (click)="addAuthor(bookIndex)">Add Author</button> </div> </div> </div> <button type="button" (click)="addBook()">Add Book</button> </div> <button type="submit">Submit</button> </form>
问题原因与修复方案
核心问题
报错的根源是表单结构与模板绑定不匹配:
- TS中
createAuthor()返回的是单个FormControl,但HTML中却用了[formGroupName]="authorIndex"——这个指令只适用于FormGroup类型的控件,不能绑定到FormControl。 - HTML中
input的formControlName="authorName"无效,因为authors数组里的元素是单个控件,不存在authorName这个键。 ngOnInit中仅调用createBook(),但未将创建的书籍表单组添加到books数组,导致初始时数组为空,触发绑定错误。
修复步骤
方案1:保持作者为单个FormControl(字符串)
修改HTML中作者循环部分的模板,去掉[formGroupName],直接绑定到FormControl:
<div formArrayName="authors"> <div *ngFor="let author of getAuthors(bookIndex).controls; let authorIndex = index"> <label> Author: <input [formControl]="author"> </label> <button type="button" (click)="removeAuthor(bookIndex, authorIndex)">Remove Author</button> </div> <button type="button" (click)="addAuthor(bookIndex)">Add Author</button> </div>
同时修正ngOnInit,将初始书籍添加到数组:
ngOnInit(): void { this.books.push(this.createBook()); }
方案2:将作者改为带字段的FormGroup(推荐,更灵活)
如果希望作者数据是包含authorName的对象,修改TS中的createAuthor()方法:
createAuthor() { return this.fb.group({ authorName: ['', Validators.required] }); }
此时原HTML模板的[formGroupName]="authorIndex"和formControlName="authorName"可以正常使用,只需修正ngOnInit的数组添加逻辑即可。
内容的提问来源于stack exchange,提问作者Joe EnDo
相关产品推荐
相关产品推荐

