ControlValueAccessor未检测到更改 - Angular 2

时间:2018-01-08 17:05:11

标签: angular

我已经实现了ControlValueAccessor,如我正在关注的教程中所示。但是,我实现controlvalueaccessor的组件似乎没有检测到对ngModel的任何更改。我错过了什么吗?

import { Component, OnInit, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
    selector: 'app-counter',
    templateUrl: './counter.component.html',
    styleUrls: ['./counter.component.css'],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => CounterComponent),
            multi: true
        }
    ]
})
export class CounterComponent implements OnInit, ControlValueAccessor {

    constructor() { }

    counterValue = 0;

    writeValue(value: any) {
        console.log('writeValue: ', value);
    }

    registerOnChange(fn: any) {
        console.log('on change: ', fn);
    }

    registerOnTouched(fn: any) {
        console.log('on touch: ', fn);
    }

    increment() {
        this.counterValue++;
    }

    decrement() {
        this.counterValue--;
    }

    ngOnInit() {
    }

}

模板:

<button (click)="increment()">Increment</button>
{{ counterValue }}
<button (click)="decrement()">Decrement</button>

<app-counter name="counter" [(ngModel)]="counter"></app-counter>

<p>ngModel: {{ counter }}</p>

在本教程的这一点上,递增/递减计数器应该触发我定义的controlvalueaccessor方法,但事实并非如此。

1 个答案:

答案 0 :(得分:1)

您必须注册更改。做那样的事情:

import {Component, OnInit, forwardRef} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';

@Component({
    selector: 'app-counter',
    template: `
        <button (click)="increment()">Increment</button>
        {{ counterValue }}
        <button (click)="decrement()">Decrement</button>
    `,
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => CounterComponent),
            multi: true
        }
    ]
})
export class CounterComponent implements ControlValueAccessor {

    constructor() { }

    counterValue = 0;

    writeValue(value: any) {
        this.counterValue = value;
    }

    registerOnChange(fn: any) {
        this.onChangeCallback = fn;
    }

    private onChangeCallback: (_: any) => void = () => {};


    registerOnTouched(fn: any) {
        console.log('on touch: ', fn);
    }

    increment() {
        this.counterValue++;
        this.onChangeCallback(this.counterValue);
    }

    decrement() {
        this.counterValue--;
        this.onChangeCallback(this.counterValue);
    }    
}

使用setter的更优雅的版本:

import {Component, OnInit, forwardRef} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';

@Component({
    selector: 'app-counter',
    template: `
        <button (click)="increment()">Increment</button>
        {{ counterValue }}
        <button (click)="decrement()">Decrement</button>
    `,
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => CounterComponent),
            multi: true
        }
    ]
})
export class CounterComponent implements ControlValueAccessor {

    private _counterValue = 0;

    get counterValue(): number {
        return this._counterValue;
    }

    set counterValue(value: number) {
        this._counterValue = value;
        this.onChangeCallback(value);
    }

    writeValue(value: any) {
        this.counterValue = value;
    }

    registerOnChange(fn: any) {
        this.onChangeCallback = fn;
    }

    private onChangeCallback: (_: any) => void = () => {};


    registerOnTouched(fn: any) {
        console.log('on touch: ', fn);
    }

    increment() {
        this._counterValue++;
    }

    decrement() {
        this._counterValue--;
    }
}

PS:请勿忘记使用writeValue()中的传入值更新内部模型,如两个示例所示。