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 相关文章推荐
JavaScript 封装Ajax传递的数据代码
Jun 05 Javascript
JavaScript 学习笔记(十四) 正则表达式
Jan 22 Javascript
Extjs列表详细信息窗口新建后自动加载解决方法
Apr 02 Javascript
拥抱模块化的JavaScript
Mar 07 Javascript
jQuery中的val()示例应用
Feb 26 Javascript
JS中操作JSON总结
Dec 06 Javascript
ajax实现动态下拉框示例
Jan 10 Javascript
JavaScript实现左右下拉框动态增删示例
Mar 09 Javascript
React.js中常用的ES6写法总结(推荐)
May 09 Javascript
jQuery动态添加li标签并添加属性和绑定事件方法
Feb 24 jQuery
官方推荐react-navigation的具体使用详解
May 08 Javascript
js嵌套的数组扁平化:将多维数组变成一维数组以及push()与concat()区别的讲解
Jan 19 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加密解密的代码
2006/10/09 PHP
php 验证码实例代码
2010/06/01 PHP
DEDE采集大师官方留后门的删除办法
2011/01/08 PHP
php常用文件操作函数汇总
2014/11/22 PHP
php获取网页里所有图片并存入数组的方法
2015/04/06 PHP
Laravel中encrypt和decrypt的实现方法
2017/09/24 PHP
客户端静态页面玩分页
2006/06/26 Javascript
使javascript也能包含文件
2006/10/26 Javascript
javascript中的作用域scope介绍
2010/12/28 Javascript
读jQuery之七 判断点击了鼠标哪个键的代码
2011/06/21 Javascript
javascript椭圆旋转相册实现代码
2012/01/16 Javascript
通过jQuery源码学习javascript(二)
2012/12/27 Javascript
JS实现动态给图片添加边框的方法
2015/04/01 Javascript
Javascript中With语句用法实例
2015/05/14 Javascript
浅谈JavaScript 浏览器对象
2016/06/03 Javascript
js数组的五种迭代方法及两种归并方法(推荐)
2016/06/14 Javascript
JavaScript——DOM操作——Window.document对象详解
2016/07/14 Javascript
jQuery.Form实现Ajax上传文件同时设置headers的方法
2017/06/26 jQuery
nodejs检测因特网是否断开的解决方案
2019/04/17 NodeJs
Python绘图实现显示中文
2019/12/04 Python
Python基础之字符串操作常用函数集合
2020/02/09 Python
使用openCV去除文字中乱入的线条实例
2020/06/02 Python
Django中和时区相关的安全问题详解
2020/10/12 Python
Python3利用scapy局域网实现自动多线程arp扫描功能
2021/01/21 Python
网页切图的CSS和布局经验与要点
2015/04/09 HTML / CSS
HTML5 canvas画图并保存成图片的jcanvas插件
2014/01/17 HTML / CSS
日本卡普空电视游戏软件公司官方购物网站:e-CAPCOM
2018/07/17 全球购物
XMLHttpRequest对象在IE和Firefox中创建方式有没有不同
2016/03/23 面试题
高中美术教学反思
2014/01/19 职场文书
办公室人员先进事迹
2014/01/27 职场文书
2014年小学国庆节活动方案
2014/09/16 职场文书
营销计划书
2015/01/17 职场文书
幼师自荐信范文
2015/03/06 职场文书
周末问候语大全
2015/11/10 职场文书
浅谈Redis主从复制以及主从复制原理
2021/05/29 Redis
OpenCV-Python实现图像平滑处理操作
2021/06/08 Python