FormArray in dynamic form angular

Well, nice work but you need to change a few things to achieve what you want.

  1. You need to change how you initialize the form array. You have named controls in your FormArray so you need to push FormGroup into your FormArray :
 for (let f of this.fields) {
      if (f.type != "array") {
        fieldsCtrls[f.name] = new FormControl(
          this.allDatas[f.name] || "",
          Validators.required
        );
      } else { // changed part
        fieldsCtrls[f.name] = new FormArray([
          ...this.allDatas[f.name].map(
            r =>
              new FormGroup(
                Object.entries(r).reduce((acc, [k, v]) => {
                  acc[k] = new FormControl(v || "", Validators.required);
                  return acc;
                }, {})
              )
          )
        ]);
      }

The above code basically generates FormGroup that has the object keys as FormControls

  1. You need to change your ArrayBox components template like below :
 <input
            attr.type="{{ obj.type }}"
            class="form-control"
            placeholder="{{ obj.name }}"
            id="{{ obj.name }}"
            name="{{ obj.name }}"
            formControlName="{{ obj.name }}"
          />

You had formControlName="{{ idx }}" which will cause Angular to seek a FormControl named 0 1 that’s one of the reasons why you get Error: Cannot find control with path: 'users -> 0 -> 0' error. The other reason is you were adding directly FormControls instead FormGroups. As your ArrayBox template states FormArray has an array of FormGroup

Working Stackblitz

As @End.Game noticed the array part still had some parts to fix. The root cause of the problem lies in the ArrayBox template. You were iterating over your configuration objects to render your form. But since it’s a FormArray you also need to repeat that template for the count of the FormArray. So you will need another *ngFor to achieve that :

   <div [formGroup]="form">
      <div formArrayName="{{ field.name }}">
        <div *ngFor="let frm of formArray.controls; index as idx">
          <div formGroupName="{{ idx }}">
            <div *ngFor="let obj of arrayFileds;">
              <input
                attr.type="{{ obj.type }}"
                class="form-control"
                placeholder="{{ obj.name }}"
                id="{{ obj.name }}"
                name="{{ obj.name }}"
                formControlName="{{ obj.name }}"
              />
            </div>
            <hr />
          </div>
        </div>
      </div>
    </div>

Please also note that moved idx variable to the parent loop.

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top