Angular使用ControlValueAccessor创建自定义表单控件


Posted in Javascript onMarch 08, 2019

在 Angular 自定义表单控件,有时你想要的输入不是标准的文本输入、选择或复选框。通过实现ControlValueAccessor 接口并将组件注册为 NG_VALUE_ACCESSOR,您可以将自定义表单控件无缝地集成到模板驱动或响应表单中,就像它是本地表单一样!

ControlValueAccessor

ControlValueAccessor 是一个接口,充当Angular API 和 DOM 元素之间的桥梁

ControlValueAccessor 是一个连接表单模型和视图(DOM元素)的接口,自定义的表单控件必须实现这个接口,它的作用是:

  • 把 form 模型中值映射到视图中
  • 当视图发生变化时,通知 form directives 或 form controls

Angular 引入这个接口的原因是,不同的输入控件数据更新方式是不一样的。例如,对于我们常用的文本输入框来说,我们是设置它的 value 值,而对于复选框 (checkbox) 我们是设置它的 checked 属性。实际上,不同类型的输入控件都有一个 ControlValueAccessor,用来更新视图

Angular 中常见的 ControlValueAccessor 有:

  • DefaultValueAccessor - 用于 text 和 textarea 类型的输入控件
  • SelectControlValueAccessor - 用于 select 选择控件
  • CheckboxControlValueAccessor - 用于 checkbox 复选控件
export interface ControlValueAccessor {
 writeValue(obj: any) : void
 registerOnChange(fn: any) : void
 registerOnTouched(fn: any) : void
}

writeValue(obj:any)是将表单模型中的值写入视图中。

writeValue(value: any): void {
 this._renderer.setProperty(this._elementRef.nativeElement, 'value', value);
}

registerOnChange(fn:any)是一个方法,用于注册在视图中的某些内容发生更改时应调用的处理程序。它获取一个函数,告诉其他表单指令和表单控件更新其值。

registerOnChange(fn: (_: any) => void): void {
 this._onChange = fn;
}

registerOnTouched(fn:any)与registerOnChange()此类似,它专门为控件接收触摸事件时注册一个处理程序。

registerOnTouched(fn: any): void {
 this._onTouched = fn;
}

setDisabledState?(isDisabled: boolean): void; 是一个可选的方法,设置自定义表单的状态

setDisabledState(isDisabled: boolean): void {
 this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
}

AbstractValueAccessor

我们可以把 ControlValueAccessor 中的方法写在一个抽象类中,不同的组件可以实现这个基类

export abstract class AbstractValueAccessor implements ControlValueAccessor {
 
 private _value: any = '';
 
 get value(): any {
 return this._value;
 }

 set value(v: any) {
 if (v !== this._value) {
  this._value = v;
  this.onChange(v);
  this.onTouched();
 }
 }

 writeValue(value: any) {
 this._value = value;
 }

 onChange = (_) => {};
 onTouched = () => {};

 registerOnChange(fn: (_: any) => void): void {
 this.onChange = fn;
 }

 registerOnTouched(fn: () => void): void {
 this.onTouched = fn;
 }
}

export function MakeProvider(type: any): { provide: any, useExisting: any, multi: boolean} {
 return { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => type), multi: true };
}

Example

自定义一个 list 控件,可以选择年级

在线预览
git仓库

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
定时器(setTimeout/setInterval)调用带参函数失效解决方法
Mar 26 Javascript
解析jquery获取父窗口的元素
Jun 26 Javascript
JS验证身份证有效性示例
Oct 11 Javascript
jQuery中triggerHandler()方法用法实例
Jan 19 Javascript
分享15个大家都熟知的jquery小技巧
Dec 02 Javascript
JavaSctit 利用FileReader和滤镜上传图片预览功能
Sep 05 Javascript
vue实现登陆登出的实现示例
Sep 15 Javascript
jQuery 开发之EasyUI 添加数据的实例
Sep 26 jQuery
vue ssr 指南详读
Jun 29 Javascript
详解vue使用插槽分发内容slot的用法
Mar 28 Javascript
JS桶排序的简单理解与实现方法示例
Nov 25 Javascript
详解JavaScript执行模型
Nov 16 Javascript
小程序测试后台服务的方法(ngrok)
Mar 08 #Javascript
详解JavaScript函数callee、call、apply的区别
Mar 08 #Javascript
利用angular自动编译andriod APK的绕坑经历分享
Mar 08 #Javascript
详解小程序循环require之坑
Mar 08 #Javascript
详解js 创建对象的几种方法
Mar 08 #Javascript
浅谈Javascript常用正则表达式应用
Mar 08 #Javascript
validform表单验证的实现方法
Mar 08 #Javascript
You might like
关于Intype一些小问题的解决办法
2008/03/28 PHP
php程序之die调试法 快速解决错误
2009/09/17 PHP
PHP图片验证码制作实现分享(全)
2012/05/10 PHP
编写安全 PHP应用程序的七个习惯深入分析
2013/06/08 PHP
codeigniter教程之上传视频并使用ffmpeg转flv示例
2014/02/13 PHP
destoon整合UCenter图文教程
2014/06/21 PHP
PHP利用hash冲突漏洞进行DDoS攻击的方法分析
2015/03/26 PHP
PHP中的traits实现代码复用使用实例
2015/05/13 PHP
详解Yii实现分页的两种方法
2017/01/14 PHP
PHP实现唤起微信支付功能
2019/02/18 PHP
微信小程序发送订阅消息的方法(php 为例)
2019/10/30 PHP
让 JavaScript 轻松支持函数重载 (Part 2 - 实现)
2009/08/04 Javascript
jQuery $.data()方法使用注意细节
2012/12/31 Javascript
浅谈JavaScript中null和undefined
2015/07/09 Javascript
JavaScript的Number对象的toString()方法
2015/12/18 Javascript
微信小程序 wxapp视图容器 view详解
2016/10/31 Javascript
浅谈html转义及防止javascript注入攻击的方法
2016/12/04 Javascript
input file样式修改以及图片预览删除功能详细概括(推荐)
2017/08/17 Javascript
js删除对象/数组中null、undefined、空对象及空数组方法示例
2018/11/14 Javascript
基于jquery实现九宫格拼图小游戏
2018/11/30 jQuery
微信公众号H5支付接口调用方法
2019/01/10 Javascript
Vue中使用canvas方法总结
2019/02/12 Javascript
LayUI数据接口返回实体封装的例子
2019/09/12 Javascript
原生js实现购物车功能
2020/09/23 Javascript
[56:20]LGD vs VP Supermajor 败者组决赛 BO3 第三场 6.10
2018/07/04 DOTA
php使用递归与迭代实现快速排序示例
2014/01/23 Python
Python中执行存储过程及获取存储过程返回值的方法
2017/10/07 Python
Python反射用法实例简析
2017/12/22 Python
Python程序运行原理图文解析
2018/02/10 Python
numpy中三维数组中加入元素后的位置详解
2019/11/28 Python
Python3加密解密库Crypto的RSA加解密和签名/验签实现方法实例
2020/02/11 Python
CSS3 filter(滤镜)实现网页灰色或者黑色模式的示例代码
2021/02/24 HTML / CSS
浅析HTML5中header标签的用法
2016/06/24 HTML / CSS
ECCO爱步美国官网:来自丹麦的鞋履品牌
2016/11/23 全球购物
优秀毕业生自我鉴定
2014/01/19 职场文书
升旗仪式主持词
2014/03/19 职场文书