[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 ...
随机推荐
- python处理文件
打开文件: open是内建函数,一个方法 open("test.txt","r",buffering=1) test.txt 表示被打开的文件名,如果不 ...
- SpringMVC,Mybatis,FreeMarker连接mycat示例(一)
首页 > 程序开发 > 软件开发 > Java > 正文 SpringMVC,Mybatis,FreeMarker连接mycat示例(一) 项目结构如图: 首先是各种配置文件, ...
- 洛谷 P1781 宇宙总统
P1781 宇宙总统 题目背景 宇宙总统竞选 题目描述 地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统. 输入输出 ...
- SJTU 3001. 二哥的幸运
Description 二哥是一个挺二的人,在二哥的世界观中,有些数字代表着幸运,假设在某一天二哥可以看到一个幸运数字,那么他将很高兴.当然,二哥对于幸运的定义也是不同凡响,假设一个数字仅仅包括4或者 ...
- 12.模板别名以及auto定义返回值
#include <iostream> #include <array> using namespace std; //定义返回值类型 template<class T1 ...
- ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第一篇:准备工作
摘要 本文将简要介绍这个文章系列的目的.形式及大体内容.并且完成开始学习这个系列前所必要的准备工作. 前言 ASP.NET MVC作为微软官方的MVC解决方案,推出有一段时间了.可 ...
- Java Web学习总结(13)——JSP入门
一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写h ...
- Costura.Fody
使用Costura.Fody将源DLL合并到目标EXE 本文为原创文章,如转载,请在网页明显位置标明原文名称.作者及网址,谢谢! 一.本文主要是使用Costura.Fody工具将源DLL合并到目标EX ...
- (转)xshell无法在vim中复制黏贴
ssh xshell 连接在vim中无法用 ctrl+insert 复制黏贴 修改.vimrc set mouse=c vi的三种模式:命令模式,插入模式,可视模式.鼠标可以启动于各种模式中: The ...
- 写PPT的先扬后抑的思路
近期给一个客户做IT战略规划. 基本结束了,客户要求写点有高度的东西.我想也是,尽管眼下的PPT也触及到战略和行业的问题,可是没有总结出来.于是就挖空心思,琢磨了三天.写了4页PPT.改动了几遍.还算 ...