Angular 组件接口之 ControlValueAccessor
ControlValueAccessor 是什么?
简单来说ControlValueAccessor是一个接口,它被用于在 Angular 的 FormControl 实例和原生 DOM 元素之间创建一个桥梁。其使用方式和OnInit类似,需要程序员在自定义组件里面实现相应的方法。
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';@Component({selector: 'custom',templateUrl: './custom.component.html',styleUrls: ['./custom.component.less'],providers: [ {provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CustomComponent),multi: true } ] }) export class CustomComponent implements ControlValueAccessor, OnInit, {…
为什么需要使用 ControlValueAccessor
有时,你可能需要创建自定义的表单元素,并希望它能和Angular的FormControl成功通信。这时你便需要ControlValueAccessor来实现这个目的。
比如:
this.myForm = new FormGroup({userName: new FormControl({value: '', disabled: false}) });
<form [formGroup]="myForm" (ngSubmit)="onSubmit()"><div class="form-group"><label>Name:<my-input formControlName="userName"></my-input></label></div><div class="form-group"><button type="submit">Submit</button></div> </form>
深入理解
ControlValueAccessor的使用方法在Angular官网和很多的文章中都有介绍,但是它具体是如何起作用的呢?
Angular 需要一种通用机制来桥接原生/自定义表单控件和 formControl 指令,而这正是 ControlValueAccessor 干的事情。这个对象桥接原生表单控件和 formControl 指令,并同步两者的值。任何一个组件或指令都可以通过实现 ControlValueAccessor 接口并注册为 NG_VALUE_ACCESSOR,从而转变成 ControlValueAccessor 类型的对象。
其实原生表单控件也拥有类似于ControlValueAccessor的接口,比如:当 Angular 在组件模板中中遇到 input 或 textarea DOM 原生控件时,就会使用DefaultValueAccessor 指令
Accessor
Form Element
DefaultValueAccessor
input,textarea
CheckboxControlValueAccessor
input[type=checkbox]
NumberValueAccessor
input[type=number]
RadioControlValueAccessor
input[type=radio]
RangeValueAccessor
input[type=range]
SelectControlValueAccessor
select
SelectMultipleControlValueAccessor
select[multiple]
以上是Angular 为所有原生 DOM 表单元素创建的 Angular 表单控件,即内置ControlValueAccessor
ControlValueAccessor 接口定义了四个方法:
- writeValue(obj:any):将表单模型中的新值写入视图或DOM属性(如果需要)的方法,它将来自外部的数据写入到内部的数据模型。
- registerOnChange(fn:any):一种注册处理程序的方法,当视图中的某些内容发生更改时应调用该处理程序。它具有一个告诉其他表单指令和表单控件以更新其值的函数。通常在 registerOnChange 中需要保存该事件触发函数,在数据改变的时候,可以通过调用事件触发函数通知外部数据变了,同时可以将修改后的数据作为参数传递出去。
- registerOnTouched(fn: any):注册 onTouched 事件,基本同 registerOnChange ,只是该函数用于通知表单组件已经处于 touched 状态,改变绑定的 FormControl 的内部状态。
- setDisabledState(isDisabled: boolean):当调用 FormControl 变更状态的 API 时得表单状态变为 Disabled 时调用 setDisabledState() 方法,以通知自定义表单组件当前表单的读写状态。
formControl 指令使用 writeValue 方法设置原生表单控件的值;使用 registerOnChange 方法来注册由每次原生表单控件值更新时触发的回调函数,我们需要把更新的值传给这个回调函数,这样对应的 Angular 表单控件值也会更新;使用 registerOnTouched 方法来注册用户和控件交互时触发的回调。
formControl会调用名为setUpControl的函数,ControlValueAccessor的实例valueAccessor会被作为参数传入这个函数中。在setUpControl中,ControlValueAccessor的四个方法会在交互时被调用,以完成formControl和元素之间的通信。
拓展:
在使用ControlValueAccessor时需要一同引入NG_VALUE_ACCESSOR,它是使用InjectionToken 创建的可在 Provider 中使用的 Token。我们在编写自己的项目时一般不需要用到InjectionToken,但是在一个框架或者第三方的插件中,它就变得十分有必要了。
export const NG_VALUE_ACCESSOR =new InjectionToken<ReadonlyArray<ControlValueAccessor>>('NgValueAccessor');
试想当我使用依赖注入的功能时,我需要将我创建的依赖注册进组件中。这时我就需要一个令牌,如果我使用一个字符串作为令牌就有可能会造成重复,相同的令牌会导致后面的覆盖前面的。所以需要一个Token作为一个唯一值来防止这种冲突。
providers: [{ provide: TOKEN, useValue: … }]
Angular 组件接口之 ControlValueAccessor相关推荐
- Angular 组件交互
Angular 组件交互 组件交互: 组件通讯,让两个或多个组件之间共享信息. 使用场景: 当某个功能在多个组件中被使用到时,可以将该特定的功能封装在一个子组件中,在子组件中处理特定的任务或工作流. ...
- 组件接口(API)设计指南-文件夹
组件接口(API)设计指南-文件夹 组件接口(API)设计指南[1]-要考虑的问题 组件接口(API)设计指南[2]-类接口(class interface) 组件接口(API)设计指南[3]-托付( ...
- angular input_快速地上手Angular组件开发
如果我会一些Javascript的基础知识,我可以快速地上手Angular吗?或者说,我是一名前端工作者,没有接触过Angular,我该如何快速地使用Angular进行日常开发呢?我是轻流前端团队的一 ...
- Angular Elements,四步将Angular 组件转换为 web 组件
Angular Elements,四步将Angular 组件转换为 web 组件 从Angular版本6开始,我们可以将Angular组件公开为Web组件,或者更确切地说:作为自定义元素,它是Web组 ...
- pb怎么封装com组件_从零开始构建 Angular 组件库
NG-ZORRO 组件库官网地址:Ant Design Of Angular Github地址:NG-ZORRO/ng-zorro-antd 更新:视频已上传 谢亚东演讲视频_腾讯视频v.qq.co ...
- 使用NG-ZORRO(Angular 组件库)中Table组件,通过columnTable属性固定列,结果每行数据内容穿透了两遍的固定列;鼠标滑过该条数据时,两侧固定列的背景色不跟着改变~
[问题] 使用NG-ZORRO(Angular 组件库)中Table组件,通过#columnTable属性固定列,结果每行数据内容穿透了两遍的固定列(因为是刚开始做这个项目,所以盲猜是之前某位同仁搞个 ...
- angular 设置接口调用地址_[译] 关于 Angular 的变化检测,你需要知道的一切
原文地址:Everything you need to know about change detection in Angular 原文作者:Max, Wizard of the Web 译文出自: ...
- elementui的tree组件页面显示不出数据_[Angular 组件库NG-ZORRO基础入门] -Hacker News: Pagination...
前言回顾 到目前为止,我们已经实现了 hacker news 大部分页面功能设计,但是仍然缺少一个重要的翻页功能,API 现在没人是返回 20 条数据,我们今天会使用 Pagination 组件 将分 ...
- Angular组件——投影
运行时动态改变组件模版的内容.没路由那么复杂,只是一段html,没有业务逻辑. ngContent指令将父组件模版上的任意片段投影到子组件上. 一.简单例子 1.子组件中使用<ng-conten ...
最新文章
- IIS Express总结
- 大数据技术 学习之旅_数据-数据科学之旅的起点
- tcp 测试软件,ztcp
- Linux内核中的常用宏container_of其实很简单【转】
- 创造性模式——原型模式
- keepalived java,keepalived 安装及使用
- Corel Painter 2022 for Mac(初学者可驾驭的绘画软件)
- Smobiler中Poplist控件的用法
- Excel读取mysql数据库
- 向量积的坐标运算公式推导_向量积的坐标运及度量公式.ppt
- 圆周率在java中的标识符_java 圆周率。
- 王森:程序设计师真情忏悔录
- 在线社交网络分析 github,在线社交网络分析软件
- already opened by ClassLoader
- FA-PEG-SH 叶酸PEG巯基
- R语言-南丁格尔玫瑰图
- 标梵分享微信官方账号运营推广思路
- TCP/IP协议、请求报文和响应报文
- 卷积核——Roberts、Prewitt、Sobel、Lapacian、DoG、LoG算子
- 模拟集成电路设计与分析——全差分放大器
热门文章
- Postman进阶篇(十二)-在脚本中使用pm对象访问接口响应数据(pm.response.*)
- 遗传算法混流装配线平衡毕业论文【matlab/Flexsim仿真】
- 用这个来代替 mail 。。更爽~
- 无方向盘!通用汽车宣布2019年生产无人驾驶汽车 | 消息
- 达梦DSC集群的备份与还原
- 简单的服务调用框架实现
- 复现:A Graph-Based Approach for Active Learning in Regression
- 火影忍者手游打秘境服务器响应超时,火影忍者打秘境版本号不一致什么情况 | 手游网游页游攻略大全...
- 企业舆情监控排查什么,TOOM讲解企业舆情监控工作方案?
- java操作derby_javaDB—— derby简单操作