[Angular] Implementing a ControlValueAccessor
So when you need to create a ControlValueAccessor?
When you want to use a custom component as form control. For example a counter component, you can custom the style and the way to control the value changes.

It needs some setup for control value accessor, but after you have done it once, you can prettty much just copy & paste the same template around to create a control value access.
import { Component, Input, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
const COUNTER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => StockCounterComponent),
multi: true
};
@Component({
selector: 'stock-counter',
providers: [COUNTER_VALUE_ACCESSOR],
styleUrls: ['stock-counter.component.scss'],
template: `
...
`
})
export class StockCounterComponent implements ControlValueAccessor {
value: number;
writeValue(val: number) {
this.value = val;
}
registerOnChange(fn: any) {
this.onModelChange = fn;
}
registerOnTouched(fn: any) {
this.onTouch = fn;
}
...
}
So the template is somehow like the code above, highly recommend to create any snippet or live template in your IDE.
So inside the component we create, we have three methods,
- writeValue(obj: any)
- registerOnChange(fn: Function)
- registerOnTouched(fn: Function)
To understand each method is the key point to understand how control value access.
So first 'writeValue':
value: number;
writeValue(val: number) {
this.value = val;
}
This is for setting initial value, we take value from our form builder and pass to our component via 'writeValue'.
<stock-counter
[step]=""
[min]=""
[max]=""
formControlName="quantity">
So the value comes from 'formControlName="quantity"'.
Now at the point, you can think that our form holds a model value and our component also holds a view value.
We need to sync model value and view value.
The way to do that is by "registerOnChange":
registerOnChange(fn: any) {
this.onModelChange = fn;
}
increment() {
this.value = this.value === this.max ?
this.value :
this.value + this.step;
this.onModelChange(this.value);
}
Every time our view value (component value) changed, to need to notify our form about the changes, we need to call 'this.onModelChange(this.value)' function and pass in the changes value.
After this form will be able to the updated value.
OK, now we able to sync the value from our component to our form. But you might think about this can be easily done by EventEmitter, when border to create Control value accessor? The most important reason is that "Validation"!
html "form" component actually does lots of thing underhook. What example, it set field state "untouch", "touched", "dirty", "prinstin". We use those status to do validation and error messages.
For example:
input.ng-touched.ng-invalid {
border-left: 5px solid red;
}
If the field is touched and is invalid, we set the border to red.
Currently, we have our value synced, and control value access also helps us to add form validation ability to our component. But once the value changed, our component still show 'ng-untouch':

So we need "registerOnTouched" function to help us to do that:
registerOnTouched(fn: any) {
this.onTouch = fn;
}
increment() {
this.value = this.value === this.max ?
this.value :
this.value + this.step;
this.onModelChange(this.value);
this.onTouch();
}
Now after the value changed, our component will be set 'ng-touched', now we are fully conver our component to a form component.
[Angular] Implementing a ControlValueAccessor的更多相关文章
- [Angular] Implementing A General Communication Mechanism For Directive Interaction
We have modal implement and now we want to implement close functionality. Becuase we use a structure ...
- [Angular] Create a ng-true-value and ng-false-value in Angular by controlValueAccessor
If you're coming from AngularJS (v1.x) you probably remember the ng-true-value and ng-false-value di ...
- Angular写一个Form组件-TagInput
前端开发少不了和表单打交道; Angular中, 提供了强大的表单的支持, 响应式表单(Reactive Form) 和 模板驱动的表单(Template-driven Form) 的双向数据流给我们 ...
- Angular Forms - 自定义 ngModel 绑定值的方式
在 Angular 应用中,我们有两种方式来实现表单绑定--"模板驱动表单"与"响应式表单".这两种方式通常能够很好的处理大部分的情况,但是对于一些特殊的表单控 ...
- angular实现简单的pagination分页组件
不想使用第三方库,只想使用一个分页器,那么就简单的实现一个,效果如下: 1.使用方式: <custom-pagination *ngIf="enterpriseList.length& ...
- [AngularFire] Angular File Uploads to Firebase Storage with Angular control value accessor
The upload class will be used in the service layer. Notice it has a constructor for file attribute, ...
- [Angular] Implement a custom form component by using control value accessor
We have a form component: <label> <h3>Type</h3> <workout-type formControlName=& ...
- angular 响应式自定义表单控件—注册头像实例
1. 组件继承ControlValueAccessor,ControlValueAccessor接口需要实现三个必选方法 writeValue() 用于向元素中写入值,获取表单的元素的元素值 regi ...
- 表单-angular
模板表单: <form #myform="ngForm" (ngSubmit)="onsubmit(myform.value)" > <div ...
随机推荐
- 高中生活-第9篇-开学之初的“失足”囧事,"刻舟求剑"导致腿折了
时间过得好快啊,上次发表"高中生活-第8篇:夏天的空调,冬天的味道"是2014年9月30日,一转眼,就是一年啊. 我自己以为,很多人可能都以为,我又半途而废了,实则不是哦~ 行百里 ...
- select into from 与 insert into select 区别
1.INSERT INTO SELECT语句 语句形式为:Insert into Table2(field1,field2,...) select value1,value2,... from Tab ...
- Android实现微信分享及注意事项
一.获取帮助文档并下载相关资料 首先打开微信开放平台:https://open.weixin.qq.com/ 如果没有注册,请先注册并上传开发者资料等待审核. 资源中心----移动应用开发----分享 ...
- 需求:在浏览器加载完毕后,自动播放视频:出现play() failed because the user didn't interact with the document first.错误
解决方法:给video标签加入<video muted></video> 静音即可. Chrome 66为了避免标签产生随机噪音. 参考链接:https://juejin.im ...
- [D3] Debug D3 v4 with Dev Tools
Since D3 outputs standard markup, you can use familiar dev tools and inspectors to debug your visual ...
- 黑马day01 xml 的解析方式
XML编程:利用java程序去增删改查(CRUD)xml中的数据 解析思想: dom解析 sax解析 基于这两种解析思想市面上就有了非常多的解析api sun jaxp既有dom方式也有sax方式,而 ...
- 硬件——nrf51822第二篇,如何设置keil用来下载程序
转自电子发烧友论坛 未完,待续...... 这里就是根据自己的项目了,并不一定是按照下面的图片去做.
- linux内核头文件 cdev.h 解析
遇到一个内核API--cdev_init 就找到这里来了. #ifndef _LINUX_CDEV_H #define _LINUX_CDEV_H #include <linux/kobject ...
- Linux定时器的使用(三种方法)
使用定时器的目的无非是为了周期性的执行某一任务,或者是到了一个指定时间去执行某一个任务.要达到这一目的,一般有两个常见的比较有效的方法.一个是用linux内部的三个定时器,另一个是用sleep, us ...
- 【习题 5-6 UVA-1595】Symmetry
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 每一个y坐标的点都找中点. 看看中点是不是都一样就好. [代码] #include <bits/stdc++.h> us ...