You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 23:18:33