Angular2 RC2 ControlValueAccessor实现中断

时间:2016-06-20 09:34:42

标签: angular

我有一个使用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,因此我不会发现任何问题。

1 个答案:

答案 0 :(得分:3)

您需要从NG_VALUE_ACCESSOR导入ControlValueAccessor@angular/forms