angularangular-reactive-formsformarray

Value is undefined in formArray


I have form array and for some reason I dont see any value in my app-input component. if I define simple formGroup contorl and pass to app-input I can see value. But in formarray happnes something weird. When I log value I see all values are undefined

form!: FormGroup<FormType>;

  get mtTypeControls(): FormGroup<mtTypesForm>[] {
    return this.form.controls.mtTypes.controls as FormGroup<mtTypesForm>[];
  }

  ngOnInit(): void {
    this.form = this.fb.nonNullable.group({
      mtTypes: this.fb.array([
        this.fb.group({
          nameEn: this.fb.control<string | null>('13'),
          nameRu: this.fb.control<string | null>('13'),
          analyzer: this.fb.control<string | null>('13'),
        }),
      ] as FormGroup<mtTypesForm>[]),
    });


 this.createForm([]);

private createForm(data: MaintenanceType[]) {
 const mtTypesGroup = new FormGroup({
      nameEn: new FormControl('123'),
      nameRu: new FormControl('333'),
      analyzer: new FormControl('333'),
    }) as FormGroup<mtTypesForm>;
this.mtTypeControls.push(mtTypesGroup);
    
     @for (group of mtTypeControls; track $index) {
        <div class="row margin-top-hg" (click)="test(mtTypeControls)">
    
            <app-input label="Name (ENG)" [formControl]="group.controls.nameEn"></app-input>
    
            <app-input label="Name (RUS)" [formControl]="group.controls.nameRu"></app-input>
     

Solution

  • The problem lies in how the HTML is structured. You should mimic the object structure.

    First we have a [formGroup]="form", then followed by a div element which should define the formArray using formArrayName="mtTypes", then the formArray will have the @for loop running for each of the form groups.

    The form elements are present inside a formGroup, so we should define the logical container of these elements using [formGroupName]="$index".

    Do not use formControl as an input property to pass in the control, this is because it is an angular directive and already has some logic executing when it's used, so use [control] instead.

    <form [formGroup]="form">
      <div formArrayName="mtTypes">
        @for (group of mtTypeControls; track $index) {
          <div class="row margin-top-hg" [formGroupName]="$index">
              <app-input label="Name (ENG)" [control]="typeAsControl(group.controls['nameEn'])"></app-input>
              <app-input label="Name (RUS)" [control]="typeAsControl(group.controls['nameRu'])"></app-input>
              <app-input label="Name (RUS)" [control]="typeAsControl(group.controls['analyzer'])"></app-input>
              <br/>
          </div>
        }
      </div>
    </form>
    

    Full Code:

    <form [formGroup]="form">
      <div formArrayName="mtTypes">
        @for (group of mtTypeControls; track $index) {
          <div class="row margin-top-hg" [formGroupName]="$index">
              <app-input label="Name (ENG)" [control]="typeAsControl(group.controls['nameEn'])"></app-input>
              <app-input label="Name (RUS)" [control]="typeAsControl(group.controls['nameRu'])"></app-input>
              <app-input label="Name (RUS)" [control]="typeAsControl(group.controls['analyzer'])"></app-input>
              <br/>
          </div>
        }
      </div>
    </form>
    

    Stackblitz Demo