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 相关文章推荐
select标签模拟/美化方法采用JS外挂式插件
Apr 01 Javascript
JavaScript中的关键字"VAR"使用详解 分享
Jul 31 Javascript
jquery隔行换色效果实现方法
Jan 15 Javascript
js实现数组转换成json
Jun 26 Javascript
html中鼠标滚轮事件onmousewheel的处理方法
Nov 11 Javascript
使用DeviceOne实现微信小程序功能
Dec 29 Javascript
Js apply方法详解
Feb 16 Javascript
Angular4项目中添加i18n国际化插件ngx-translate的步骤详解
Jul 02 Javascript
Vue 莹石摄像头直播视频实例代码
Aug 31 Javascript
详解React 服务端渲染方案完美的解决方案
Dec 14 Javascript
为nuxt项目写一个面包屑cli工具实现自动生成页面与面包屑配置
Sep 29 Javascript
JS箭头函数和常规函数之间的区别实例分析【 5 个区别】
May 27 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
西德产收音机
2021/03/01 无线电
php获取服务器端mac和客户端mac的地址支持WIN/LINUX
2014/05/15 PHP
CI框架中通过hook的方式实现简单的权限控制
2015/01/07 PHP
php将print_r处理后的数据还原为原始数组的解决方法
2016/11/02 PHP
OAuth认证协议中的HMACSHA1加密算法(实例)
2017/10/25 PHP
PHP7新功能总结
2019/04/14 PHP
用JS判断IE版本的代码 超管用!
2011/08/09 Javascript
纯js网页画板(Graphics)类简介及实现代码
2012/12/24 Javascript
js单例模式详解实例
2013/11/21 Javascript
javascript计算星座属相(十二生肖属相)示例代码
2014/01/09 Javascript
不使用jquery实现js打字效果示例分享
2014/01/19 Javascript
javascript为按钮注册回车事件(设置默认按钮)的方法
2015/05/09 Javascript
JavaScript让Textarea支持tab按键的方法
2015/06/26 Javascript
Dojo获取下拉框的文本和值实例代码
2016/05/27 Javascript
JavaScript知识点总结(六)之JavaScript判断变量数据类型
2016/05/31 Javascript
禁用backspace网页回退功能的实现代码
2016/11/15 Javascript
浅谈express 中间件机制及实现原理
2017/08/31 Javascript
vue微信分享 vue实现当前页面分享其他页面
2017/12/02 Javascript
浅谈React 服务器端渲染的使用
2018/05/08 Javascript
angular ng-model 无法获取值的处理方法
2018/10/02 Javascript
原生JS实现列表内容自动向上滚动效果
2019/05/22 Javascript
vue选项卡切换登录方式小案例
2019/09/27 Javascript
解决vue项目本地启动时无法携带cookie的问题
2021/02/06 Vue.js
[58:29]DOTA2-DPC中国联赛 正赛 Phoenix vs XG BO3 第一场 1月31日
2021/03/11 DOTA
django 实现电子支付功能的示例代码
2018/07/25 Python
python flask web服务实现更换默认端口和IP的方法
2019/07/26 Python
Python开发之基于模板匹配的信用卡数字识别功能
2020/01/13 Python
美国葡萄酒网上商店:Martha Stewart Wine Co.
2019/03/17 全球购物
德国排名第一的主题公园门票网站:Attraction Tickets Direct
2019/09/09 全球购物
房地产还款计划书
2014/01/10 职场文书
职工运动会邀请函
2014/01/19 职场文书
双十佳事迹材料
2014/01/29 职场文书
感恩父母的演讲稿
2014/05/06 职场文书
房屋租赁协议书(标准版)
2014/10/02 职场文书
linux下安装redis图文详细步骤
2021/12/04 Redis
CentOS7设置ssh服务以及端口修改方式
2022/12/24 Servers