ControlValueAccessor not detecting changes - Angular 2



我已经实现了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 方法,但事实并非如此。

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

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()中的传入值更新内部模型,如两个示例所示。

最新更新