本文简单介绍封装使用ngModel实现自定义表单控件的过程。
NgModel 相关
NgModel
NgModel用于从作用域创建一个FormControl实例,并将它绑定到一个表单控件元素。
- [ngModel]: 单向绑定,作用域变更将同步到UI中
- [(ngModel)]: 双向绑定,UI模板的变更页将同步到作用域中
ngModel继承自NgControl
NgControl
NgControl是所有控制指令继承的基础类。它将一个FormControl绑定到DOM元素中。
FormControl、FormGroup、FormArray,三者都用于angular表单的值和状态的跟踪,区别是一个控件、一组控件或者是它们的组合。
FormControl用于跟踪一个单独的表单控件的值和有效性状态。它对应一个HTML表单控件,不如输入框和下拉框。
FormGroup用于跟踪一组AbstractControl的实例的值和有效性状态。该组的属性中包含了它的子控件。组件中的顶级表单就是一个FormGroup。
FormArray用于跟踪AbstractControl实例组成的有序数组的值和有效性状态。
ControlValueAccessor
ControlValueAccessor用于在控制和原生元素之间建立联系,它封装了赋值到一个表现为input元素的DOM元素。
简单说,就是angular中的input是带有[(ngModel)]这个属性的,而我们想要自己控制这个input的写入过程,使用ControlValueAccessor就可以做到。
ControlValueAccessor提供以下接口:
writeValue(obj: any) : void:写入值到元素registerOnChange(fn: any) : void:设置当控件接收到change事件时触发的回调registerOnTouched(fn: any) : void:设置当控件接收到touch事件时触发的回调setDisabledState(isDisabled: boolean) : void:该函数将在控件状态或者disabled值变化,根据值来对元素启用或失效
DefaultValueAccessor
DefaultValueAccessor提供值写入和监听变化的默认访问,像NgModel, FormControlDirective, 和FormControlName指令会使用。
DefaultValueAccessor提供类包括:
onChange : (_: any) => {}change事件变化监听onTouched : () => {}touch事件变化监听
以及ControlValueAccessor(上面)的接口。
NG_VALUE_ACCESSOR
NG_VALUE_ACCESSOR提供一个ControlValueAccessor供表单控制使用。
创建自定义input控件
我们想要封装后的组件跟原生的angular组件一样,像表现为input的自定义控件,我们想要使用[(ngModel)]来进行双向绑定,我们需要使用ControlValueAccessor来拓展。
而这里ControlValueAccessor只是一个接口,我们应用它,还需要获取一些可用的服务,这时候需要注入NG_VALUE_ACCESSOR。
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true
};
这里简单讲讲几个概念:
- 我们自定义了一个访问控制服务,该服务包装为
NG_VALUE_ACCESSOR服务,主要用于控制ControlValueAccessor相关的访问。 - 我们需要将自定义input控件提供给
NG_VALUE_ACCESSOR,以便通过自定义方式控制父组件的[(ngModel)]以及其他表单相关的访问。 forwardRef用于将目前还未获取到的依赖关联起来,这里我们关联后面的自定义Input组件。
@Component({
selector: 'app-custom-input',
templateUrl: './custom-input.component.html',
styleUrls: ['./custom-input.component.css'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true
}
]
})
export class CustomInputComponent implements OnInit, ControlValueAccessor {
/*
* 自定义表单控件
* 需要完成ControlValueAccessor内部的方法
* */
private _custom: any = '';
// 定义ControlValueAccessor提供的事件回调
private onChange = (_: any) => {
};
get custom(): any {
return this._custom;
}
set custom(v: any) {
if (v !== this._custom) {
this._custom = v;
this.onChange(this._custom);
}
}
constructor() {
}
ngOnInit() {
}
writeValue(val: any): void {
this._custom = val;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
}
}
本文介绍如何使用ngModel和ControlValueAccessor封装自定义表单控件,实现与Angular原生input相同的[(ngModel)]双向绑定功能。
2676

被折叠的 条评论
为什么被折叠?



