我有一个使用ControlValueAccessor接口的自定义控件,但自从升级到angular2 rc2(来自rc1)后,我得到以下异常:
EXCEPTION: Error: Uncaught (in promise): EXCEPTION: Error in templates/assetDefinition/options-editor-select.component.html:3:15
ORIGINAL EXCEPTION: No value accessor for ''
ORIGINAL STACKTRACE: Error: No value accessor for ''
at new BaseException (http://localhost:5000/js/app-es6.js:4129:23)
at _throwError (http://localhost:5000/js/app-es6.js:39145:11)
at Object.setUpControl (http://localhost:5000/js/app-es6.js:39120:9)
at NgModel._addStandaloneControl (http://localhost:5000/js/app-es6.js:38205:18)
at NgModel._addControl (http://localhost:5000/js/app-es6.js:38201:18)
at NgModel.ngOnChanges (http://localhost:5000/js/app-es6.js:38159:18)
at DebugAppView._View_OptionsEditorSelectComponent0.detectChangesInternal (OptionsEditorSelectComponent.template.js:120:47)
at DebugAppView.AppView.detectChanges (http://localhost:5000/js/app-es6.js:32254:14)
at DebugAppView.detectChanges (http://localhost:5000/js/app-es6.js:32359:44)
at DebugAppView.AppView.detectViewChildrenChanges (http://localhost:5000/js/app-es6.js:32280:19)
我的组件代码是(BaseComponent只设置一些属性,如'icons'):
import {Component, Output, EventEmitter, Provider, forwardRef} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR, CORE_DIRECTIVES} from '@angular/common';
import {BaseComponent} from '../Components/base.component';
const TAG_CREATOR_CONTROL_VALUE_ACCESSOR = new Provider(
NG_VALUE_ACCESSOR,
{
useExisting: forwardRef(() => TagCreatorComponent),
multi: true
});
@Component({
selector: 'tag-creator',
templateUrl: 'templates/shared/tag-creator.component.html',
directives: [CORE_DIRECTIVES],
providers: [TAG_CREATOR_CONTROL_VALUE_ACCESSOR]
})
export class TagCreatorComponent extends BaseComponent implements ControlValueAccessor{
constructor() {
super();
}
@Output() change = new EventEmitter();
private _values: string[];
private _onTouchedCallback: () => void = () => undefined
private _onChangeCallback: (val: string[]) => void = () => undefined
get values(): string[] {
return this._values;
}
set values(s: string[]) {
if (s !== this.values && !s.every(x => this.values.indexOf(x) > -1)) {
this._values = s;
this._onChangeCallback(s);
}
}
onTouched() {
this._onTouchedCallback();
}
newTag: string = "";
valueIsValid: boolean = true;
input(event) {
const tag = event.target.value.trim();
this.valueIsValid = this.values.indexOf(tag) === -1;
}
keyPress(event) {
if (event.keyCode === 13 && this.isValid) {
this.values.push(this.newTag);
this.newTag = "";
this._onChangeCallback(this.values);
this.change.emit(this.values);
}
}
removeTag(tag) {
this.values.splice(this.values.indexOf(tag), 1);
this._onChangeCallback(this.values);
this.change.emit(this.values);
}
writeValue(value: string[]) {
this._values = value;
}
registerOnChange(fn: any) {
this._onChangeCallback = fn;
}
registerOnTouched(fn: any) {
this._onTouchedCallback = fn;
}
}
使用以下模板:
<div class="tag-creator">
<div class="tag-holder">
<div class="tag" *ngFor="let tag of values">
<span>{{tag}} <i class="fa" (click)="removeTag(tag)">{{icons.cross}}</i></span>
</div>
</div>
<input class="tag-input form-control input-sm"
[(ngModel)]="newTag"
(input)="input($event)"
(keypress)="keyPress($event)"
[class.input-success]="valueIsValid"
[class.input-danger]="!valueIsValid"/>
</div>
我已经检查过官方changelog,并且没有提及框架的这一部分的变化。正如您所看到的,我没有使用任何已更改的表单API,因此我不会发现任何问题。
答案 0 :(得分:3)
您需要从NG_VALUE_ACCESSOR
导入ControlValueAccessor
和@angular/forms
。