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 相关文章推荐
执行iframe中的javascript方法
Oct 07 Javascript
javascript getElementsByTagName
Jan 31 Javascript
JS动态获取当前时间,并写到特定的区域
May 03 Javascript
JS判断浏览器是否支持某一个CSS3属性的方法
Oct 17 Javascript
js正则匹配出所有图片及图片地址src的方法
Jun 08 Javascript
基于Bootstrap实现Material Design风格表单插件 附源码下载
Apr 18 Javascript
js获取隐藏元素宽高的实现方法
May 19 Javascript
移动端使用localStorage缓存Js和css文的方法(web开发)
Sep 20 Javascript
AngularJS读取JSON及XML文件的方法示例
May 25 Javascript
微信小程序媒体组件详解(视频,音乐,图片)
Sep 19 Javascript
基于AngularJS拖拽插件ngDraggable.js实现拖拽排序功能
Apr 02 Javascript
Vue 幸运大转盘实现思路详解
May 06 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
php入门之连接mysql数据库的一个类
2012/04/21 PHP
基于flush()不能按顺序输出时的解决办法
2013/06/29 PHP
PHP实现限制IP访问及提交次数的方法详解
2017/07/17 PHP
关于Anemometer图形化显示MySQL慢日志的工具搭建及使用的详细介绍
2020/07/13 PHP
node.js入门教程迷你书、node.js入门web应用开发完全示例
2014/04/06 Javascript
JS+CSS实现的简单折叠展开多级菜单效果
2015/09/12 Javascript
jquery删除table当前行的实例代码
2016/10/07 Javascript
jquery插入兄弟节点的操作方法
2016/12/07 Javascript
从零开始搭建一个react项目开发
2018/02/09 Javascript
详解在React.js中使用PureComponent的重要性和使用方式
2018/07/10 Javascript
vue.js 实现评价五角星组件的实例代码
2018/08/13 Javascript
react build 后打包发布总结
2018/08/24 Javascript
vue.js 子组件无法获取父组件store值的解决方式
2019/11/08 Javascript
详解钉钉小程序组件之自定义模态框(弹窗封装实现)
2020/03/07 Javascript
NestJs使用Mongoose对MongoDB操作的方法
2021/02/22 Javascript
[01:28:31]《加油DOTA》真人秀 第五期
2014/09/01 DOTA
[52:10]LGD vs Optic Supermajor小组赛D组胜者组决赛 BO3 第二场 6.3
2018/06/04 DOTA
探究Python的Tornado框架对子域名和泛域名的支持
2015/05/02 Python
Python自动化开发学习之三级菜单制作
2017/07/14 Python
Python File readlines() 使用方法
2018/03/19 Python
对TensorFlow的assign赋值用法详解
2018/07/30 Python
python中matplotlib条件背景颜色的实现
2019/09/02 Python
python实现批量修改文件名
2020/03/23 Python
爱尔兰电子产品购物网站:Komplett.ie
2018/04/04 全球购物
Otticanet意大利:最顶尖的世界名牌眼镜, 能得到打折季的价格
2019/03/10 全球购物
eDreams加拿大:廉价航班、酒店和度假
2019/03/29 全球购物
2014年幼儿园小班工作总结
2014/12/04 职场文书
2014年小学数学工作总结
2014/12/12 职场文书
争先创优个人总结
2015/03/04 职场文书
2015年班组建设工作总结
2015/05/13 职场文书
毕业论文致谢格式模板
2015/05/14 职场文书
宪法宣传标语100条
2019/10/15 职场文书
导游词之吉林花园山
2019/10/17 职场文书
python3美化表格数据输出结果的实现代码
2021/04/14 Python
Vue提供的三种调试方式你知道吗
2022/01/18 Vue.js
vue 把二维或多维数组转一维数组
2022/04/24 Vue.js