Javascript Angular4 - 表单控件没有值访问器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45659742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular4 - No value accessor for form control
提问by jbtd
I have a custom element :
我有一个自定义元素:
<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>
When I try to add the formControlName, I get an error message:
当我尝试添加 formControlName 时,我收到一条错误消息:
ERROR Error: No value accessor for form control with name: 'surveyType'
错误错误:没有名称的表单控件的值访问器:'surveyType'
I tried to add ngDefaultControlwithout success.
It seems it's because there is no input/select... and I dont know what to do.
我尝试添加ngDefaultControl但没有成功。似乎是因为没有输入/选择......我不知道该怎么办。
I would like to bind my click to this formControl in order that when someone clicks on the entire card that would push my 'type' into the formControl. Is it possible?
我想将我的点击绑定到这个 formControl,以便当有人点击整个卡片时,将我的“类型”推入 formControl。是否可以?
回答by Lazar Ljubenovi?
You can use formControlNameonly on directives which implement ControlValueAccessor.
您formControlName只能在实现ControlValueAccessor.
Implement the interface
实现接口
So, in order to do what you want, you have to create a component which implements ControlValueAccessor, which means implementing the following three functions:
所以,为了做你想做的,你必须创建一个实现的组件ControlValueAccessor,这意味着实现以下三个功能:
writeValue(tells Angular how to write value from model into view)registerOnChange(registers a handler function that is called when the view changes)registerOnTouched(registers a handler to be called when the component receives a touch event, useful for knowing if the component has been focused).
writeValue(告诉 Angular 如何将模型中的值写入视图)registerOnChange(注册一个在视图改变时调用的处理函数)registerOnTouched(注册一个在组件接收到触摸事件时要调用的处理程序,有助于了解组件是否已获得焦点)。
Register a provider
注册提供商
Then, you have to tell Angular that this directive is a ControlValueAccessor(interface is not gonna cut it since it is stripped from the code when TypeScript is compiled to JavaScript). You do this by registering a provider.
然后,你必须告诉 Angular 这个指令是一个ControlValueAccessor(接口不会削减它,因为它在 TypeScript 被编译为 JavaScript 时从代码中剥离)。您可以通过注册提供程序来完成此操作。
The provider should provide NG_VALUE_ACCESSORand use an existing value. You'll also need a forwardRefhere. Note that NG_VALUE_ACCESSORshould be a multi provider.
提供者应提供NG_VALUE_ACCESSOR并使用现有值。你还需要一个forwardRef在这里。注意NG_VALUE_ACCESSOR应该是多提供者。
For example, if your custom directive is named MyControlComponent, you should add something along the following lines inside the object passed to @Componentdecorator:
例如,如果您的自定义指令名为 MyControlComponent,您应该在传递给@Component装饰器的对象中添加以下几行内容:
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => MyControlComponent),
}
]
Usage
用法
Your component is ready to be used. With template-driven forms, ngModelbinding will now work properly.
您的组件已准备好使用。使用模板驱动的表单,ngModel绑定现在可以正常工作。
With reactive forms, you can now properly use formControlNameand the form control will behave as expected.
使用响应式表单,您现在可以正确使用formControlName,表单控件将按预期运行。
Resources
资源
回答by Vega
I think you should use formControlName="surveyType"on an inputand not on a div
我认为你应该使用formControlName="surveyType"oninput而不是div
回答by Sudhir Singh
For me it was due to "multiple" attribute on select input control as Angular has different ValueAccessor for this type of control.
对我来说,这是由于选择输入控件上的“多个”属性,因为 Angular 对这种类型的控件具有不同的 ValueAccessor。
const countryControl = new FormControl();
And inside template use like this
在模板内部像这样使用
<select multiple name="countries" [formControl]="countryControl">
<option *ngFor="let country of countries" [ngValue]="country">
{{ country.name }}
</option>
</select>
More details ref Official Docs
更多细节参考官方文档

