Home > Blockchain >  Angular problem with FormArray in FormArray
Angular problem with FormArray in FormArray

Time:08-25

I am working on a dynamic Form in Angular. There should be an array in another array.

But it has a problem with my form and the following error appears:

[Cannot find control with path: 'gruppen -> 0 -> prueffolge'][1] I have a object structure like this:

"pruefplanTemplate": {
  "gruppen": [
      "prueffolge": 100,
      "name": "test",
      "pruefungen": [
        "..": "",
        "..": ""
      ]
  ]
}

This is my code: Component:

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);
  }
}

Template:

<h3>Prüfplan erstellen:</h3>
<p>{{this.gruppen.length}}</p>
<div  [formGroup]="form">
    <ng-container formArrayName="gruppen">
        <ng-container *ngFor="let gruppeForm of gruppen.controls; let i = index">
            <div  [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  (click)="deleteGruppe(i)">delete_forever</mat-icon>

                <ng-container formArrayName="pruefungen">
                    <ng-container *ngFor="let pruefschritt of getPruefung(i, gruppeForm); let j = index">
                        <div  [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 >add</mat-icon>
            </button>
        </ng-container>
    </ng-container>

    <button mat-mini-fab (click)="addPruefplanGruppe();">
        Gruppe
        <mat-icon >add</mat-icon>
    </button>
</div>

Model:

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;
}

I hope someone has more experience with FormArray than me!

Thank you guys! [1]: https://i.stack.imgur.com/hEAGL.png

CodePudding user response:

When we use a FormArray, always use a "getter" to get the formArray. If we has a formArray of FormArray, we cannot use a "getter" else a function with an index

So you has

get gruppen()
{
    return this.form.get("gruppen") as FormArray;
}

getPruefungen(index:number)
{
   return this.gruppen.at(index).get('pruefungen') as FromArray
}

Now is "as always"

<form [formGroup]="form">
  <div formArrayName="gruppen">
     <div *ngFor="let group of gruppen.controls;let i=index" [formGroupName]="i">
         <input formControlName="prueffolge">
         ....
 
         <!--see that it's the same constructor for the inner
             but use getPruefungen(i) -->
         <div formArrayName="pruefungen">
             <div *ngFor="let group of getPruefungen(i).controls;let j=index" 
                                                              [formGroupName]="j">
                <input formControlName="beschreibung">
                 ....
             </div>
         </div>
     </div>
  </div>
</form>

CodePudding user response:

The problem is that you need to define your pruefungen as a FormArray not ForControl, like this:

addPruefplanGruppe() {
    const gruppeForm = this.fb.group({
      prueffolge: [100, Validators.required],
      name: ['', Validators.required],
      pruefungen: this.fb.array([]).  // <---- see this line
    });

    this.gruppen.push(gruppeForm);
  }


  • Related