NG_VALUE_ACCESSOR
用于为表单控件提供 ControlValueAccessor
interface ControlValueAccessor {
writeValue(obj: any): void
registerOnChange(fn: any): void
registerOnTouched(fn: any): void
setDisabledState(isDisabled: boolean)?: void
}
双向绑定 示例组件:
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
forwardRef,
} from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
@Component({
selector: 'my-input',
styleUrls: ['./my.input.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MyInputComponent),
multi: true,
},
],
template: `
<input type="text" #inputElement
[(ngModel)]="value"
(ngModelChange)="modelChange($event)"/>
<button (click)="clickMe()">change</button>
`
})
export class MyInputComponent implements ControlValueAccessor {
private onTouch = () => {};
private onChange = (newValue: any) => {};
value = '';
index = 0; // for test manual change value
constructor(
private cdr: ChangeDetectorRef
) { }
clickMe() {
const v = 'index : ' + (++this.index);
this.value = v;
this.onChange(v);
}
modelChange(newValue: string) {
this.onChange(newValue);
}
// ControlValueAccessor -
// 至少需要实现 writeValue, registerOnChange,registerOnTouched
writeValue(v: any) {
if (v !== this.value) {
this.value = v;
}
// on push
this.cdr.markForCheck();
}
registerOnChange(fn: any) {
this.onChange = fn;
}
registerOnTouched(fn: any) {
this.onTouch = fn;
}
}
registerOnTouched 的参数 fn:
registerOnChange 的参数 fn :