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 ...
最新文章
- matlab图形绘制经典案例,MATLAB经典教程第四章_图形绘制.ppt
- 白大脑比超级计算机还,和超级计算机相比,人类的大脑很弱吗
- java获取jsp_JSP、JAVA获取各种路径总结
- JVM编译时和运行时状态
- Swift开发:NSLayoutConstraint纯代码实现自动布局-初级篇
- Linux命令【五】系统函数
- mysql极客_极客mysql16
- 整数大小比较(信息学奥赛一本通-T1043)
- 论开心网和人人网的衰落
- dcp9030cdn定影_兄弟DCP-9030CDN驱动
- PS使用技巧(一) 移动工具 V
- 贝叶斯分类器,什么是朴素贝叶斯,后续为使用贝叶斯实现海量数据的邮件筛选。带源码数据集和解决思路
- 科学计算机后盖换电池,图吧小白教程 篇二十二:手把手教你给手机换电池(拆机)...
- python绘制的Svg图打开一片空白
- (23)Linux基础-系统磁盘阵列raid
- 物联卡一直显示待激活怎么办_物联卡开始要求活体认证,这种纯流量卡你以后还管乱使用吗?...
- 【电机/控制理论】DTC(Direct Torque Control)直接转矩控制
- .Net Core通过NPOI在CentOS 7(Docker)环境中导出Excel报错The type initializer for ‘Gdip‘ 的问题
- 产品三大文档BRD/MRD/PRD
- 食品行业质量追溯系统的建设(一)