angulartypescriptangular-reactive-formsformarrayformgroups

Angular - ERROR Error: Cannot find control with name: 's..Address'


I have the following component in HTML:

<div>
    <form [formGroup]="dynamicFormGroup" (ngSubmit)="onSubmit()">
        <div class="form-row" *ngFor="let fields of AddressInfo.controls; let i = index" >
            <div class="form-group col-md-3" >
                <label for="password"><b>Street Address</b></label>
                <input type="text" class="form-control" placeholder="Street Address" name="SA" formControlName="streetAddress" />
              </div>
              <div class="form-group col-md-3" >
                <label for="password"><b>City</b></label>
                <input type="text" class="form-control" placeholder="City" name="city" formControlName="city" />
              </div>
              <div class="form-group col-md-3" >
                <label for="password"><b>State</b></label>
                <input type="text" class="form-control" placeholder="State" name="state" formControlName="state" />
              </div>
        </div>
        <br/>
     <button type="submit"  class="btn btn-primary">Submit</button>
    </form>
    <br/>
    <button type = "button" class="btn btn-primary" (click)="addNewAddress()" >Add New Address</button>
</div>    

<h4>OUTPUT</h4>
<div>{{output}}</div>

and .ts file:

import { Component, OnInit } from '@angular/core';
import { FormArray, FormBuilder, FormGroup } from '@angular/forms';

@Component({
  selector: 'app-dynamic-form',
  templateUrl: './dynamic-form.component.html',
  styleUrls: ['./dynamic-form.component.css'],
})
export class DynamicFormComponent implements OnInit {
  dynamicFormGroup!: FormGroup;
  output!: any;
  constructor(private formBuilder: FormBuilder) {}

  ngOnInit() {
    this.dynamicFormGroup = this.formBuilder.group({
      address: new FormArray([this.createItem]),
    });
  }

  addNewAddress(): void {
    (this.dynamicFormGroup.get('address') as FormArray).push(this.createItem);
  }

  get formControllers() {
    return this.dynamicFormGroup.controls;
  }

  get AddressInfo() {
    return this.formControllers['address'] as FormArray;
  }

  get createItem(): FormGroup {
    return this.formBuilder.group({
      streetAddress: [],
      city: [],
      state: [],
    });
  }
  onSubmit() {
    this.output = this.dynamicFormGroup.controls['address'].value;
    console.log(this.output);
  }
}

Getting this error:

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

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

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

Using this link:

https://dev.to/mana95/how-to-handle-dynamic-form-fields-in-reactive-forms-in-angular-3c0f

https://codesandbox.io/p/devbox/hardcore-goldberg-ytsxn5?file=%2Fsrc%2Fapp%2Fdynamic-form%2Fdynamic-form.component.html%3A1%2C1-25%2C22

Any solution? Thanks.


Solution

  • Your Reactive Form structure in HTML was incorrect:

    1. Missing the formArrayName="address" attribute.

    2. The mentioned controls should be wrapped in the FormGroup.

    <div
      class="form-row"
      formArrayName="address"
      *ngFor="let fields of AddressInfo.controls; let i = index"
    >
      <ng-container [formGroupName]="i">
        <div class="form-group col-md-3">
          <label for="password"><b>Street Address</b></label>
          <input
            type="text"
            class="form-control"
            placeholder="Street Address"
            name="SA"
            formControlName="streetAddress"
          />
        </div>
        <div class="form-group col-md-3">
          <label for="password"><b>City</b></label>
          <input
            type="text"
            class="form-control"
            placeholder="City"
            name="city"
            formControlName="city"
          />
        </div>
        <div class="form-group col-md-3">
          <label for="password"><b>State</b></label>
          <input
            type="text"
            class="form-control"
            placeholder="State"
            name="state"
            formControlName="state"
          />
        </div>
      </ng-container>
    </div>
    

    Demo @ StackBlitz