我有这样的简单自定义输入组件,
import {Component, Provider, forwardRef} from "@angular/core";
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from "@angular/forms";
const noop = () => {};
const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true
};
@Component({
selector: 'custom-input',
template: `
<input class="form-control"
[(ngModel)]="value" name="somename"
(blur)="onTouched()">
`,
providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class CustomInputComponent implements ControlValueAccessor{
//The internal data model
private _value: any = '';
//Placeholders for the callbacks
private _onTouchedCallback: () => void = noop;
private _onChangeCallback: (_:any) => void = noop;
//get accessor
get value(): any { return this._value; };
//set accessor including call the onchange callback
set value(v: any) {
if (v !== this._value) {
this._value = v;
this._onChangeCallback(v);
}
}
//Set touched on blur
onTouched(){
this._onTouchedCallback();
}
//From ControlValueAccessor interface
writeValue(value: any) {
this._value = value;
}
//From ControlValueAccessor interface
registerOnChange(fn: any) {
this._onChangeCallback = fn;
}
//From ControlValueAccessor interface
registerOnTouched(fn: any) {
this._onTouchedCallback = fn;
}
}
我有这样的app模块,
/**
* Created by amare on 8/15/16.
*/
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { AppComponent } from './app/app.component';
import {CustomInputComponent} from "./app/shared/custom.input.component";
import {RouterModule} from "@angular/router";
@NgModule({
imports: [ BrowserModule, ReactiveFormsModule, FormsModule, RouterModule ],
declarations: [ AppComponent, CustomInputComponent],
bootstrap: [ AppComponent ]
})
export class AppModule {
}
和主要
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
我已经在我的一个组件中使用了我的自定义输入,如下所示,但是我得到'没有用于具有未指定名称属性的表单控件的值访问器'。
<custom-input name="firstName" [(ngModel)]="firstName"></custom-input>
,app.component看起来像这样
import { Component } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css']
})
export class AppComponent {
title = 'app works!';
firstName: string;
}
答案 0 :(得分:68)
将ngDefaultControl添加到主机中的自定义输入组件解决了问题,感谢@danieleds
答案 1 :(得分:45)
将ngDefaultControl添加到自定义输入组件。这增加了双向数据绑定,除非你做一些独特的事情,否则你不应该实现值访问器方法。
<custom-input name="firstName" [(ngModel)]="firstName" ngDefaultControl></custom-input>
答案 2 :(得分:10)
将ngDefaultControl
添加到您的输入中。例如
<inline-editor type="textarea" [(ngModel)]="editableTextArea" (onSave)="saveEditable($event)" value="valor" ngDefaultControl> </inline-editor>
然后import { FORM_DIRECTIVES } from '@angular/common'
;
最后指令:[FORM_DIRECTIVES]
这将有效:)感谢上述评论
答案 3 :(得分:2)
我在自己的[(ngModel)]
标签上放了<option>
而不是<select>
是的...这会导致这种情况。
答案 4 :(得分:0)
在出现这种情况的另一种情况下,我在最近重建和简化的自定义组件上指定了[(ngModel)]
,并且该组件的新版本仅将ngModel
作为常规输入变量发出。
这还不够-输入变量必须重命名为ngModel
以外的名称,否则组件必须实现ControlValueAccessor
接口(see the docs for details)。一旦一个完成,您将不再收到此错误。