Angular 8 - FormArray“没有用于带有路径的表单控制的值访问器”

Nei*_*l89 4 form-control angular-ngselect angular formarray

我在表单上使用ng-select,但现在我想将其特定配置包装在自定义组件上。问题是我正在使用FormArray包含其中几个的 a,以下面的方式:

this.profileForm = this.formBuilder.group(
  {
    ...
    linkedRoles: this.formBuilder.array([])
  }
);
Run Code Online (Sandbox Code Playgroud)

linkedRoles由下一个填充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])
  });
Run Code Online (Sandbox Code Playgroud)

为了简单起见,还创建了 getter:

get linkedRoles(): FormArray {
  return <FormArray>this.profileForm.get("linkedRoles");
}
Run Code Online (Sandbox Code Playgroud)

之后,在我的模板中,我使用了这个效果完美的组合:

<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>
Run Code Online (Sandbox Code Playgroud)

现在,我尝试ng-select用我的自定义组件替换role-selector,该组件基本上从 接收所有必要的属性ng-select并将其包装在模板中。我之前的模板修改如下:

<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>
Run Code Online (Sandbox Code Playgroud)

通过这个微妙的变化,我在控制台中收到下一个错误:

ERROR Error: No value accessor for form control with path: 'linkedRoles -> 0 -> roles'
Run Code Online (Sandbox Code Playgroud)

最奇怪的是,当我单击出现的无样式框时,它加载并工作得几乎正常。我应该将标签移到组件模板内部formControlName吗?ng-select

可能的解决方案

在寻找解决方案时,我发现了有趣的ngDefaultControl. 将此指令添加到我的自定义组件中可以使其按预期运行。现在看起来像这样:

<app-role-selector
  [hideSelected]="false"
  bindLabel="rol"
  ...
  ngDefaultControl
  formControlName="roles"
>
Run Code Online (Sandbox Code Playgroud)

唯一的反面是我不完全理解为什么这是必要的以及这是否是最好的解决方案。

小智 9

我知道这不是OP的问题,但如果它对任何人有帮助的话,我在我的设置中收到了类似的错误。我使用 Angular 13,使用 Angular Material 和 FormArray。我的数组中的表单控件使用mat-checkbox

简单的修复,我忘记将“MatCheckboxModule”导入到我的模块中。现在不再有错误了。这对我来说绝对是误导,因为我认为这是一个表单问题,而不是缺少模块。希望对任何人有帮助


Owe*_*vin 5

错误说No value accessor for form control with path: 'linkedRoles -> 0 -> roles'

要解决此问题,首先要找到名称为 的控件roles。这是ng-select。但我们知道ng-select有一个ValueAccessor......那么为什么 Angular 会抱怨呢?

原因基本上是您尚未导入NgSelectModule声明组件的模块。

但为什么 Angular 不抱怨未知元素呢?请参阅此链接Ivy 没有抱怨 ng-template #36171 中的未知元素。Angular 不会抱怨未知元素,但会抱怨ValueAccessor