angularangular-materialangular-reactive-formsformarraymat-form-field

<mat-form-field> component doesn't work properly with FormArray and formGroupName


The input field is not displayed with the appearance of <mat-form-field> before clicking inside when formGroupName is used with FormArray.

See the example:

TS:

formMain = this.fb.group({
    details: this.fb.array([
      new FormGroup({
        label: new FormControl(''),
        description: new FormControl(''),
      }),
    ]),
  });

  get detailsFormArray() {
    return this.formMain.controls.details as FormArray;
  }

  addDetails() {
    this.detailsFormArray.push(this.fb.control(''));
  }
}

HTML:

<form [formGroup]="formMain">
  <div formArrayName="details">
    <div
      *ngFor="let detail of detailsFormArray.controls; index as i"
      [formGroupName]="i"
    >
      <mat-form-field appearance="fill">
        <mat-label>Label of a detail</mat-label>
        <input id="detail-label" matInput type="text" formControlName="label" />
      </mat-form-field>

      <mat-form-field appearance="fill">
        <mat-label>Description of a detail</mat-label>
        <input
          id="detail-description"
          matInput
          type="text"
          formControlName="description"
        />
      </mat-form-field>
    </div>
  </div>
</form>

<br />

<button type="button" (click)="addDetails()">+ Add Details</button>


After clicking Add Details and before clicking in the form:

and

and after clicking in the form:

Is there a solution to this problem?


Solution

  • You are not adding the FormGroup instance to details FormArray correctly. Currently, you are adding the FormControl instance.

    Would recommend writing a shared function to create the FormGroup instance.

    formMain = this.fb.group({
      details: this.fb.array([this.addDetailsFormGroup()]),
    });
    
    addDetails() {
      this.detailsFormArray.push(this.addDetailsFormGroup());
    }
    
    addDetailsFormGroup() {
      return new FormGroup({
        label: new FormControl(''),
        description: new FormControl(''),
      });
    }
    

    Demo @ StackBlitz