常见的
ngmodel
的使用场景是在form
表单相关的地方,比如input
、select
等。不过很多时候我们可能需要定义、封装一些符合自己或者项目的组件,这个时候,组件可能本身就和input
、select
等没有太大区别,只是添加了一些自定义的设置,那么如何去实现ngmodel
的绑定呢
需求说明
基本的需求可以用如下的代码来解释
<self-def-input [(ngModel)]="value"></self-def-input>
如上所示,我们自定义了一个元素self-def-input
。这个元素绑定了一个变量value
,我们能够实时的实现value
的双向绑定。
实现
看起来,似乎很简单,但是,具体的如何实现呢?
话不多说,上代码:
import { ControlValueAccessor } from '@angular/forms/src/directives';
import { Component, forwardRef, Input } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'u-input',
template: `
<input [(ngModel)]="value">
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => UnionInputComponent),
multi: true
}
]
})
export class UnionInputComponent implements ControlValueAccessor {
constructor() {}
private innerValue: any = '';
private onTouchedCallback: () => void = function(){};
private onChangeCallback: (_: any) => void = function(){};
get value(): any {
return this.innerValue;
}
set value(v: any) {
if (v !== this.innerValue) {
this.innerValue = v;
this.onChangeCallback(v);
}
}
writeValue(value: any) {
if (value !== this.innerValue) {
this.innerValue = value;
}
}
registerOnChange(fn: any) {
this.onChangeCallback = fn;
}
registerOnTouched(fn: any) {
this.onTouchedCallback = fn;
}
}