1.在自定义的表单组件中,需要实现ControlValueAccessor接口,这个接口的作用有两个:
在自定义的表单组件中实现ControlValueAccessor接口的方式是将其注册为NG_VALUE_ACCESSOR:
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => KyCheckboxComponent ),
multi: true,
},
],
另外接口ControlValueAccessor中有三个必须实现的的方法:
// model view -> view value
writeValue(value: any): void {
this.kyChecked = value;
}
// view value ->model value
registerOnChange(fn: any): void {
this.onModelChange = fn;
}
registerOnTouched(fn: any): void {
this._onTouched = fn;
}
setDisabledState(isDisabled: boolean): void {
this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
}
您通过以上操作,便可以以将自定义表单控件无缝地集成到模板驱动或响应表单中,就像它是本地表单一样!
注:writeValue和registerOnChange是实现ngModel双向绑定的关键(具体可参看ky-checkbox组件)
以下为ky-checkbox组件代码:
import {
Component,
Input,
forwardRef,
ViewEncapsulation,
Output,
EventEmitter,
} from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { InputBoolean } from 'ng-zorro-antd';
@Component({
selector: 'ky-checkbox',
template: `
`,
styles: [
`
label {
display: block;
padding: 5px 0;
}
.mobile .ant-checkbox-wrapper.checked {
background: #e9eeff;
border-color: #7490e7;
}
`,
],
encapsulation: ViewEncapsulation.None,
host: {
'[class.ky-checkbox-wrapper]': 'true',
},
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => KyCheckboxComponent),
multi: true,
},
],
})
export class KyCheckboxComponent implements ControlValueAccessor {
@Input() mode: 'web' | 'mobile' = 'web';
@Input() @InputBoolean() kyChecked = false;
@Input() @InputBoolean() kyDisabled = false;
@Output() kyCheckedChange: EventEmitter<boolean> = new EventEmitter();
onModelChange = (T) => {};
// model view -> view value
writeValue(value: any): void {
this.kyChecked = value;
}
// view value ->model value
registerOnChange(fn: any): void {
this.onModelChange = fn;
}
registerOnTouched(): void {}
setDisabledState(isDisabled: boolean): void {}
onCheckChange(newValue: boolean): void {
this.kyChecked = newValue;
this.onModelChange(newValue);
this.kyCheckedChange.emit(newValue);
}
}