我已经实现了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方法,但事实并非如此。
答案 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()
中的传入值更新内部模型,如两个示例所示。