Angular嵌套FormArray动态表单报错:找不到指定控件路径
Angular动态表单嵌套数组报错解决:
Cannot find control with path: 'gruppen -> 0 -> prueffolge' 问题概述
开发Angular动态表单实现数组嵌套数组结构时,出现报错:Cannot find control with path: 'gruppen -> 0 -> prueffolge'
数据结构
"pruefplanTemplate": { "gruppen": [ { "prueffolge": 100, "name": "test", "pruefungen": [ { "beschreibung": "", "erledigt": false, "reaktion": "", "bemerkung": "" } ] } ] }
原代码
组件代码
import { Component, OnInit } from '@angular/core'; import { AbstractControl, FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-pruefplan-template', templateUrl: './pruefplan-template.component.html', styleUrls: ['./pruefplan-template.component.scss'] }) export class PruefplanTemplateComponent implements OnInit { form = this.fb.group({ gruppen: this.fb.array([ new FormGroup({ pruefungen: this.fb.array([]) }) ]) }); constructor(private fb: FormBuilder) { } ngOnInit(): void { } get gruppen() { return this.form.controls["gruppen"] as FormArray; } addPruefplanGruppe() { const gruppeForm = this.fb.group({ prueffolge: [100, Validators.required], name: ['', Validators.required], pruefungen: [[]] }); this.gruppen.push(gruppeForm); } deleteGruppe(gruppenIndex: number) { this.gruppen.removeAt(gruppenIndex); } getPruefung(index: number, control: any): AbstractControl[] { var pruefungen = control[index].controls; return pruefungen; } addPruefschritt(index: number, gruppe: any) { var formArray = gruppe.controls['pruefungen'] as FormArray; const pruefschrittForm = this.fb.group({ beschreibung: ['', Validators.required], erledigt: [false, Validators.required], reaktion: ['', Validators.required], bemerkung: ['', Validators.required] }); this.getPruefung(index, gruppe).push(pruefschrittForm); } }
模板代码
<h3>Prüfplan erstellen:</h3> <p>{{this.gruppen.length}}</p> <div class="add-lessons-form" [formGroup]="form"> <ng-container formArrayName="gruppen"> <ng-container *ngFor="let gruppeForm of gruppen.controls; let i = index"> <div class="lesson-form-row" [formGroupName]="i"> <mat-form-field appearance="fill"> <input matInput formControlName="prueffolge" placeholder="Prüffolge"> </mat-form-field> <mat-form-field appearance="fill"> <input matInput formControlName="name" placeholder="Name"> </mat-form-field> <mat-icon class="delete-btn" (click)="deleteGruppe(i)">delete_forever</mat-icon> <ng-container formArrayName="pruefungen"> <ng-container *ngFor="let pruefschritt of getPruefung(i, gruppeForm); let j = index"> <div class="pruefschritt-form-row" [formGroupName]="j"> <mat-form-field appearance="fill"> <input matInput formControlName="beschreibung" placeholder="Beschreibung"> </mat-form-field> <mat-form-field appearance="fill"> <input matInput formControlName="erledigt" placeholder="Erledigt"> //TODO: Boolean </mat-form-field> <mat-form-field appearance="fill"> <input matInput formControlName="reaktion" placeholder="Reaktion"> </mat-form-field> <mat-form-field appearance="fill"> <input matInput formControlName="bemerkung" placeholder="Bemerkung"> </mat-form-field> </div> </ng-container> </ng-container> </div> <button mat-mini-fab (click)="addPruefschritt(i, gruppeForm);"> Prüfschritt <mat-icon class="add-course-btn">add</mat-icon> </button> </ng-container> </ng-container> <button mat-mini-fab (click)="addPruefplanGruppe();"> Gruppe <mat-icon class="add-course-btn">add</mat-icon> </button> </div>
模型代码
export interface PruefplanTemplate { gruppen: Gruppe[]; } export interface Gruppe { prueffolge: number; name: string; pruefungen: Pruefung[]; } export interface Pruefung { beschreibung: string; erledigt: boolean; reaktion: string; bemerkung: string; }
错误分析与修正方案
1. 初始表单控件缺失
原代码中初始的gruppen FormArray里的FormGroup只包含pruefungen控件,缺少prueffolge和name,但模板中绑定了这两个控件,导致找不到对应控件报错。
修正: 封装创建Gruppe表单的方法,确保初始表单和新增表单结构一致:
private createGruppeForm(): FormGroup { return this.fb.group({ prueffolge: [100, Validators.required], name: ['', Validators.required], pruefungen: this.fb.array([]) }); } // 初始化表单 form = this.fb.group({ gruppen: this.fb.array([this.createGruppeForm()]) });
2. pruefungen类型错误
原addPruefplanGruppe方法中,pruefungen被初始化为普通数组[],但它应该是FormArray类型。
修正: 复用createGruppeForm方法创建新增的Gruppe表单,确保pruefungen是FormArray:
addPruefplanGruppe() { this.gruppen.push(this.createGruppeForm()); }
3. 获取pruefungen的方法逻辑错误
原getPruefung方法用index去获取控件,逻辑错误,应该直接从当前Gruppe表单中获取pruefungen FormArray。
修正: 重写获取方法:
getPruefungen(gruppeForm: AbstractControl): FormArray { return gruppeForm.get('pruefungen') as FormArray; }
4. 新增Pruefschritt的逻辑错误
原addPruefschritt方法错误地调用getPruefung去push控件,应该直接操作pruefungen FormArray。
修正:
addPruefschritt(gruppeForm: AbstractControl) { const pruefungenArray = this.getPruefungen(gruppeForm); pruefungenArray.push(this.fb.group({ beschreibung: ['', Validators.required], erledigt: [false, Validators.required], reaktion: ['', Validators.required], bemerkung: ['', Validators.required] })); }
5. 模板中遍历pruefungen的错误
原模板中遍历getPruefung(i, gruppeForm)的逻辑错误,应该遍历getPruefungen(gruppeForm).controls。另外erledigt是布尔值,应该用mat-checkbox代替input。
修正模板:
<ng-container formArrayName="pruefungen"> <ng-container *ngFor="let pruefschritt of getPruefungen(gruppeForm).controls; let j = index"> <div class="pruefschritt-form-row" [formGroupName]="j"> <mat-form-field appearance="fill"> <input matInput formControlName="beschreibung" placeholder="Beschreibung"> </mat-form-field> <mat-checkbox formControlName="erledigt">Erledigt</mat-checkbox> <mat-form-field appearance="fill"> <input matInput formControlName="reaktion" placeholder="Reaktion"> </mat-form-field> <mat-form-field appearance="fill"> <input matInput formControlName="bemerkung" placeholder="Bemerkung"> </mat-form-field> </div> </ng-container> </ng-container> <!-- 新增Prüfschritt按钮的调用修正 --> <button mat-mini-fab (click)="addPruefschritt(gruppeForm);"> Prüfschritt <mat-icon class="add-course-btn">add</mat-icon> </button>
完整修正后组件代码
import { Component, OnInit } from '@angular/core'; import { AbstractControl, FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-pruefplan-template', templateUrl: './pruefplan-template.component.html', styleUrls: ['./pruefplan-template.component.scss'] }) export class PruefplanTemplateComponent implements OnInit { form = this.fb.group({ gruppen: this.fb.array([this.createGruppeForm()]) }); constructor(private fb: FormBuilder) { } ngOnInit(): void { } get gruppen() { return this.form.controls["gruppen"] as FormArray; } private createGruppeForm(): FormGroup { return this.fb.group({ prueffolge: [100, Validators.required], name: ['', Validators.required], pruefungen: this.fb.array([]) }); } addPruefplanGruppe() { this.gruppen.push(this.createGruppeForm()); } deleteGruppe(gruppenIndex: number) { this.gruppen.removeAt(gruppenIndex); } getPruefungen(gruppeForm: AbstractControl): FormArray { return gruppeForm.get('pruefungen') as FormArray; } addPruefschritt(gruppeForm: AbstractControl) { const pruefungenArray = this.getPruefungen(gruppeForm); pruefungenArray.push(this.fb.group({ beschreibung: ['', Validators.required], erledigt: [false, Validators.required], reaktion: ['', Validators.required], bemerkung: ['', Validators.required] })); } }
内容的提问来源于stack exchange,提问作者Marci
相关产品推荐
相关产品推荐

