Search code examples
angularform-controlformarrayformgroups

How to access the formControlName of a nested FormGroup inside a FormArray


I might be totally wrong with the way I'm managing the form and the information here. If so, I'm sorry everyone but I'm kind of lost here...

Here's my form:

private tpForm = this.fb.group({
    name: [null, Validators.required],
    vat: [null, Validators.required],
    activityNumber: [null],
    addresses: this.fb.array([
      this.createAddress()
    ])
  });

  constructor(private fb: FormBuilder) { }

  createAddress(): FormGroup {
    return this.fb.group({
      street: [null, Validators.required],
      streetComp: [null],
      streetComp2: [null],
      city: [null, Validators.required],
      cp: [null, Validators.required],
      state: [null],
      country: [null, Validators.required]
    });
  }

important side-note:

  1. the form is private
  2. there's a constructor in there

because it comes from a service that generates the form which is adapted for different models. But you get the idea of the overall structure of the form.

My objective is to be able to add more than one address if necessary and each address is a FormGroup Object because it is, in itself, sort of a form.

the thing is, I can't seem to access the controls included in the FormGroup, itself nested in the FormArray:

<mat-card-content>
      <mat-grid-list cols="3" rowHeight="1.2:1">
        <form [formGroup]="tpForm" (ngSubmit)="onSubmit()">
        <mat-grid-tile formGroupName="tpForm"> //<--- Here I'm trying to divide the access to the controls (name, vat, activityNumber) this one gives me an error (see below)
            <mat-form-field appearance="outline">
              <mat-label>Customer VAT Number</mat-label>
              <input matInput formControlName="vat">
              <mat-error *ngIf="tpForm.get('vat').invalid">Please enter a VAT number!</mat-error>
              <mat-icon matSuffix *ngIf="tpForm.get('vat').valid || !editing">sentiment_very_satisfied</mat-icon>
              <mat-hint>Customer's local VAT number</mat-hint>
            </mat-form-field>
            <button style="margin: 0.5rem;" mat-raised-button type="button" color="accent" (click)="onLoadInfo()" [disabled]="tpForm.get('vat').invalid || !editing">Load information</button>
            <mat-form-field appearance="fill">
              <mat-label>Customer name</mat-label>
              <input matInput formControlName="name">
              <mat-error *ngIf="tpForm.get('name').invalid">Please enter the customer's name</mat-error>
              <mat-icon matSuffix *ngIf="tpForm.get('name').valid || !editing">sentiment_very_satisfied</mat-icon>
              <mat-hint>Has to match the customer full legal name</mat-hint>
            </mat-form-field>
            <mat-form-field appearance="fill">
              <mat-label>Customer Activity Reference</mat-label>
              <input matInput formControlName="activityNumber">
              <mat-icon matSuffix *ngIf="tpForm.get('activityNumber').value">sentiment_very_satisfied</mat-icon>
              <mat-hint>Customer's local activity reference (INSEE, CNAE...)</mat-hint>
            </mat-form-field>
          </mat-grid-tile>
          <mat-grid-tile formGroupName="tpForm.get('addresses')[0]">//<--- So that I can get the controls from the addresses here 
            <mat-form-field appearance="fill">
              <mat-label>Street</mat-label>
              <input matInput formControlName="street">
              <mat-icon matSuffix *ngIf="tpForm.get('addresses')[0].get('street').value">sentiment_very_satisfied</mat-icon>
              <mat-hint>Customer's local activity reference (INSEE, CNAE...)</mat-hint>
           </mat-form-field>
         </mat-grid-tile>
       </form>
  </mat-grid-list>
</mat-card-content>

For now, not I'm not too surprised about it. All this yields on the following error:

ERROR Error: Cannot find control with name: 'tpForm'

Pointing to the line in my code (see the comment) <mat-grid-tile formGroupName="tpForm">

I'm a bit lit lost in translation and would love your input on how to handle this. Many thanks in advance!


Solution

  • <form [formGroup]="tpForm" (ngSubmit)="onSubmit()">
        <mat-grid-tile formGroupName="tpForm"> 
    

    That is wrong, since you don't have any form group named "tpForm" inside the main form group named "tpForm". Remove that useless formGroupName="tpForm".

    formGroupName="tpForm.get('addresses')[0]"
    

    That is wrong, too. tpForm.get() returns a form control. You must pass the name of a form group to formGroupName.

    You need something like

    <div formArrayName="addresses"> <!-- addresses is the name of the form array inside the owning form group tpForm -->
        <div [formGroupName]="0"> <!-- 0 is the index of form group inside the owning form array addresses -->
            <input formControlName="street"> <!-- street is the name of the form control inside the owning form group 0 -->