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.

Code

[Angular] Implementing a ControlValueAccessor的更多相关文章

  1. [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 ...

  2. [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 ...

  3. Angular写一个Form组件-TagInput

    前端开发少不了和表单打交道; Angular中, 提供了强大的表单的支持, 响应式表单(Reactive Form) 和 模板驱动的表单(Template-driven Form) 的双向数据流给我们 ...

  4. Angular Forms - 自定义 ngModel 绑定值的方式

    在 Angular 应用中,我们有两种方式来实现表单绑定--"模板驱动表单"与"响应式表单".这两种方式通常能够很好的处理大部分的情况,但是对于一些特殊的表单控 ...

  5. angular实现简单的pagination分页组件

    不想使用第三方库,只想使用一个分页器,那么就简单的实现一个,效果如下: 1.使用方式: <custom-pagination *ngIf="enterpriseList.length& ...

  6. [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, ...

  7. [Angular] Implement a custom form component by using control value accessor

    We have a form component: <label> <h3>Type</h3> <workout-type formControlName=& ...

  8. angular 响应式自定义表单控件—注册头像实例

    1. 组件继承ControlValueAccessor,ControlValueAccessor接口需要实现三个必选方法 writeValue() 用于向元素中写入值,获取表单的元素的元素值 regi ...

  9. 表单-angular

    模板表单: <form #myform="ngForm" (ngSubmit)="onsubmit(myform.value)" > <div ...

随机推荐

  1. gulp几个常见问题及解决方案

    1. 找不到local gulp 报错代码: $ gulp [23:29:31] Local gulp not found in [23:29:31] Try running: npm install ...

  2. 读阮一峰《ECMAScript 6 入门》小结

    读阮一峰<ECMAScript 6 入门>小结,http://es6.ruanyifeng.com/ 1. ES6简介 Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转 ...

  3. BZOJ1023: [SHOI2008]cactus仙人掌图(仙人掌)

    Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的 ...

  4. JS如何动态生成变量名[重点]

    解决方案: function create_variable(num){           var name = "test_"+num;   //生成函数名           ...

  5. Python图片的横坐标汉字

    给一个例子 : # -*- coding: utf-8 -*-import matplotlib.pyplot as plt  import py_hanzi as ch         #关键在于这 ...

  6. GO语言学习(十七)Go 语言类型转换

    Go 语言类型转换 类型转换用于将一种数据类型的变量转换为另外一种类型的变量.Go 语言类型转换基本格式如下: type_name(expression) type_name 为类型,expressi ...

  7. 洛谷—— P1967 货车运输 || COGS——C 1439. [NOIP2013]货车运输

    https://www.luogu.org/problem/show?pid=1967#sub  ||  http://www.cogs.pro/cogs/problem/problem.php?pi ...

  8. Android Studio - no debuggable applications 的解决的方法

    之前logcat总是无法显示调试应用的信息 曾经我都是卸载重装.后来发如今StackOverflow有一个哥们说的非常对.一次就成功. 原话是这么说的: You also should have To ...

  9. iOS_06_基本运算符

    一.算术运算 c语言一共有34种运算符,包括了常见的加减乘除 1.加法运算+ # 除了能做加法运算,还能表示正号:+5.+90 2.减法运算- # 除了能做减法运算,还能表示符号:-10.-200 3 ...

  10. ds1302模块的一个arduino程序

    /* * 读写DS1302 时钟芯片 * @author Yangtf * 很棒的文档 http://www.21ic.com/jichuzhishi/datasheet/DS1302/data/18 ...