您好,欢迎访问一九零五行业门户网

详解Angular使用ControlValueAccessor实现自定义表单控件

本篇文章给大家介绍一下angular使用controlvalueaccessor实现自定义表单控件的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。
angular: [controlvalueaccessor] 自定义表单控件我们在实际开发中,通常会遇到各种各样的定制化功能,会遇到有些组件会与 angular 的表单进行交互,这时候我们一般会从外部传入一个 formgroup 对象,然后在组件的内部写相应的逻辑对 angular 表单进行操作。如果我们只是对表单中的一个项进行定制,将整个表单对象传入显然不合适,并且组件也会显得臃肿。
<form [formgroup]="simpleform">
<other-component [form]="simpleform"></other-component>
</form>

那么,我们能不能像原生表单一样去使用这些自定义组件呢?目前,开源组件 ng-zorro-antd 表单组件能和原生表单一样使用 formcontrolname 这个属性,这类组件就叫自定义表单组件。【相关推荐:《angular教程》】
如何实现自定义表单控件在 angular 中,使用 controlvalueaccessor 可以实现组件与外层包裹的 form 关联起来。
controlvalueaccessor是用于处理以下内容的接口:
将表单模型中的值写入视图/ dom在视图/ dom更改时通知其他表单指令和控件controlvalueaccessor
controlvalueaccessor 接口定义了四个方法:
writevalue(obj: any): void
registeronchange(fn: any): void
registerontouched(fn: any): void
setdisabledstate(isdisabled: boolean)?: void

writevalue(obj:any):将表单模型中的新值写入视图或dom属性(如果需要)的方法,它将来自外部的数据写入到内部的数据模型。数据流向: form model -> component。
registeronchange(fn:any):一种注册处理程序的方法,当视图中的某些内容发生更改时应调用该处理程序。它具有一个告诉其他表单指令和表单控件以更新其值的函数。通常在 registeronchange 中需要保存该事件触发函数,在数据改变的时候,可以通过调用事件触发函数通知外部数据变了,同时可以将修改后的数据作为参数传递出去。数据流向: component -> form model。
registerontouched(fn: any):注册 ontouched 事件,基本同 registeronchange ,只是该函数用于通知表单组件已经处于 touched 状态,改变绑定的 formcontrol 的内部状态。状态变更: component -> form model。
setdisabledstate(isdisabled: boolean):当调用 formcontrol 变更状态的 api 时得表单状态变为 disabled 时调用 setdisabledstate() 方法,以通知自定义表单组件当前表单的读写状态。状态变更: form model -> component。
如何使用 controlvalueaccessor搭建控件框架
@component({
selector: 'app-test-control-value-accessor',
templateurl: './test-control-value-accessor.component.html',
providers: [{
provide: ng_value_accessor,
useexisting: forwardref(() => testcontrolvalueaccessorcomponent),
multi: true
}]
})
export class testcontrolvalueaccessorcomponent implements controlvalueaccessor {
_countervalue = 0;
private onchange = (_: any) => {};
constructor() { }
get countervalue() {
return this._countervalue;
}
set countervalue(value) {
this._countervalue = value;
// 触发 onchange,component 内部的值同步到 form model
this.onchange(this._countervalue);
}
increment() {
this.countervalue++;
}
decrement() {
this.countervalue--;
}
// form model 的值同步到 component 内部
writevalue(obj: any): void {
if (obj !== undefined) {
this.countervalue = obj;
}
}
registeronchange(fn: any): void {
this.onchange = fn;
}
registerontouched(fn: any): void { }
setdisabledstate?(isdisabled: boolean): void { }
}

注册 controlvalueaccessor
为了获得 controlvalueaccessor 用于表单控件,angular 内部将注入在 ng_value_accessor 令牌上注册的所有值,这是将控件本身注册到 di 框架成为一个可以让表单访问其值的控件。因此,我们需要做的就是ng_value_accessor 使用我们自己的值访问器实例(这是我们的组件)扩展 multi-provider 。所以设置 multi: true,是声明这个 token 对应的类很多,分散在各处。
这里我们必须使用 useexisting,因为testcontrolvalueaccessorcomponent 可能在使用它的组件中被其创建为指令依赖项。这就得用到 forwardref 了,这个函数允许我们引用一个尚未定义的对象。
@component({
...
providers: [
{
provide: ng_value_accessor,
useexisting: forwardref(() => testcontrolvalueaccessorcomponent ),
multi: true
}
]
})
export class testcontrolvalueaccessorcomponent implements controlvalueaccessor {
...
}

控件界面
test-control-value-accessor.component.html<div class="panel panel-primary">
<div class="panel-heading">自定义控件</div>
<div class="panel-body">
<button (click)="increment()">+</button>
{{countervalue}}
<button (click)="decrement()">-</button>
</div>
</div>

在表单中使用
app.component.html<div class="constainer">
<form #form="ngform">
<app-test-control-value-accessor name="message" [(ngmodel)]="message"></app-test-control-value-accessor>
<button type="button" (click)="submit(form.value)">submit</button>
</form>
<pre>{{ message }}</pre>
</div>

app.component.ts@component({
selector: 'app-root',
templateurl: './app.component.html',
styleurls: ['./app.component.css']
})
export class appcomponent {
message = 5;
submit(value: any): void {
console.log(value);
}
}

参考https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html
https://almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel
https://juejin.im/post/597176886fb9a06ba4746d15
https://github.com/shhdgit/blogs/issues/11
更多编程相关知识,请访问:编程视频!!
以上就是详解angular使用controlvalueaccessor实现自定义表单控件的详细内容。
其它类似信息

推荐信息