Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 8 - FormArray "No value accessor for form control with path"

I'm using ng-select on a form, but now I want to wrap a specific configuration of this on a custom component. The problem is I'm using a FormArray which contains several of this, in the next way:

this.profileForm = this.formBuilder.group(
  {
    ...
    linkedRoles: this.formBuilder.array([])
  }
);

This linkedRoles is populated with the next FormGroup:

let fgRoles: FormGroup;

for (let i = 0; i < this.userRoles.length; i++) {
  fgRoles = this.formBuilder.group({
    activeRole: [{ value: null }],
    roles: [{ value: null }]
  });
  this.linkedRoles.push(fgRoles);
  this.linkedRoles.controls[i].setValue({
    activeRole: this.userRoles[i].role,
    roles: this.extractUserRoles(this.userRoles[i])
  });

A getter is created for simplicity too:

get linkedRoles(): FormArray {
  return <FormArray>this.profileForm.get("linkedRoles");
}

After this, in my template, I was using this composition which was working perfectly:

<form [formGroup]="profileForm">
  ...

  <table>
    ...
    <tbody>
      <tr formArrayName="linkedRoles"
        *ngFor="let usuR of userRoles;
          let idx = index"
      >
        ...
        <td data-label="Roles" [formGroupName]="idx">
          <ng-select #rolesNgSelect
            [hideSelected]="false"
            bindLabel="rol"
            ...
            formControlName="roles"
          >

            <ng-template ng-label-tmp let-item="item">
              ...
            </ng-template>

            <ng-template ng-option-tmp let-item="item">
              ...
            </ng-template>

          </ng-select>
        </td>
      </tr>
    </tbody>
  </table>

</form>

Now, I'm trying to substitute the ng-select by my custom component role-selector, which basically receives all the necessary properties from the ng-select and wraps this in the template. The change in my previous template is as follows:

<tr formArrayName="linkedRoles"
  *ngFor="let usuR of userRoles;
    let idx = index;
    let ctrlRol of linkedRoles.controls"
>
  <td>
    <app-role-selector
      [hideSelected]="false"
      bindLabel="rol"
      ...
      formControlName="roles"
    >
    </app-role-selector>
  </td>
</tr>

With this subtle change, I'm receiving the next error in console:

ERROR Error: No value accessor for form control with path: 'linkedRoles -> 0 -> roles'

Strangest thing is, when I click the unstyled box that appears, it loads and works almost fine. Should I move my formControlName tag to the ng-select inside my component's template?

POSSIBLE SOLUTION

Looking for a solution, I found the interesting ngDefaultControl. Adding this directive to my custom component makes it behave as expected. Now it looks like this:

<app-role-selector
  [hideSelected]="false"
  bindLabel="rol"
  ...
  ngDefaultControl
  formControlName="roles"
>

The only counterside is I don't fully understand why this is necessary and if this is the best solution.

like image 264
Neil89 Avatar asked Nov 01 '25 14:11

Neil89


1 Answers

I know this is not the OP's problem but if it helps anyone, I received a similar error, with my setup. I'm in Angular 13, using Angular Material, and a FormArray. Where a form control in my array uses a mat-checkbox.

Simple fix, I forgot to import the 'MatCheckboxModule' into my module. And now no more errors. Definitely misleading for me, as I thought it was a form issue, not a missing module. Hope that helps anyone

like image 110
BrianInPhx Avatar answered Nov 04 '25 06:11

BrianInPhx



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!