philip yoo
philip yoo

Reputation: 2512

Angular Reactive Form: Using a FormArray and adjusting the FormControls leads to Error There is no form control element for path

I'm creating a filterable table. The first column contains checkboxes for selecting rows, and eventually the user can do some actions with the selections.

On filter, I am doing:

public resetFormRows(items: any[]) {
    this.formGroup.removeControl('rows');
    const newRows = items.map(_ => new FormControl(false));
    const newFormArray = new FormArray(newRows);
    this.formGroup.addControl('rows', newFormArray);
}

After filtering the table, I can console.log the controls and see that the FormArray contains the new FormControl. However, when I select the checkbox for a row that shifted (i.e. changed row index), the following error is shown:

ERROR Error: There is no FormControl instance attached to form control element with path: 'rows -> 1'

Here is a stackblitz that demonstrates the bug: https://stackblitz.com/edit/angular-8-template-form-fzsyse?file=src%2Fapp%2Ftable.component.ts

To get the error to show, perform the following:

I have a few questions:

Upvotes: 2

Views: 2953

Answers (2)

jagjeet
jagjeet

Reputation: 595

your form array contains formcontrols but they dont have any name so you can not access them using formControlName

to fix this:

in ts:

  get formArray() {
      return this.myForm.controls.rows as FormArray;
  }

in html

<input type="checkbox" checkBoxDirective [formControl]="formArray.controls[i]" />

working stackblitz link :

https://stackblitz.com/edit/angular-8-template-form-8xnmdp?file=src%2Fapp%2Ftable.component.html

Upvotes: 1

Chellappan வ
Chellappan வ

Reputation: 27293

Instead of using formControlName directive, try using formControl standalone directive as mentioned in the thread:

Try this:

    <tr *ngFor="let item of filteredData$ | async; index as i">
        <td>
            <label><input type="checkbox" checkBoxDirective [formControl]="myForm.get('rows').controls[i]" /></label>
        </td>
        <td>
            {{ item.name }}     
        </td> 
    </tr>

Forked Example

Upvotes: 5

Related Questions