Angular4 - 用于表单控制的无值访问器实现接口注册提供商用法资源

我有一个自定义元素:

<div formControlName="surveyType">
  <div *ngFor="let type of surveyTypes"
       (click)="onSelectType(type)"
       [class.selected]="type === selectedType">
    <md-icon>{{ type.icon }}</md-icon>
    <span>{{ type.description }}</span>
  </div>
</div>

当我尝试添加表单控件名称时,我收到一条错误消息:

错误错误:名称为“调查类型”的窗体控件没有值访问器

我试图添加,但没有成功。这似乎是因为没有输入/选择...我不知道该怎么办。ngDefaultControl

我想将我的点击绑定到此表单控件,以便当有人单击整个卡时,会将我的“类型”推入表单控件。可能吗?


答案 1

您只能在实现 ControlValueAccessor 的指令上使用。formControlName

实现接口

因此,为了做你想做的事情,你必须创建一个实现 ControlValueAccessor 的组件,这意味着实现以下三个函数

  • writeValue(告诉Angular如何将模型的值写入视图)
  • registerOnChange(注册在视图更改时调用的处理程序函数)
  • registerOnTouched(注册一个处理程序,以便在组件收到触摸事件时调用,这对于了解组件是否已获得焦点非常有用)。

注册提供商

然后,你必须告诉Angular这个指令是一个(接口不会削减它,因为当TypeScript编译为JavaScript时,它会从代码中剥离出来)。您可以通过注册提供程序来执行此操作。ControlValueAccessor

提供程序应提供NG_VALUE_ACCESSOR并使用现有值。您还需要在此处使用 forwardRef。请注意,应该是多提供程序NG_VALUE_ACCESSOR

例如,如果您的自定义指令名为 MyControlComponent,则应在传递给装饰器的对象中添加以下行的内容:@Component

providers: [
  { 
    provide: NG_VALUE_ACCESSOR,
    multi: true,
    useExisting: forwardRef(() => MyControlComponent),
  }
]

用法

您的组件已准备就绪,可供使用。使用模板驱动的表单,绑定现在可以正常工作。ngModel

使用反应式窗体,您现在可以正确使用,窗体控件将按预期方式运行。formControlName

资源


答案 2

您应该在 上使用,而不是在formControlName="surveyType"inputdiv