Introduction

In this article, I will explain about how to implement control value accessor in Angular. Control Value Accessor is an interface that provides us the power to leverage the Angular forms API and create a communication between Angular Form API and the DOM element. It provides us many facilities in angular like we can create custom controls or custom component with the help of control value accessor interface.

Prerequisites

For this article, I have created an Angular project using Angular 12. For creating an Angular project, we need to follow the following steps:

Create Project

I have created a project using the following command in the Command Prompt.

JavaScript
ng new controlValueAccessorExample

Open a project in Visual Studio Code using the following commands.

JavaScript
cd controlValueAccessorExample
Code .

Now in Visual Studio your project looks like as below.

Let's create Custom Component using the following command:

JavaScript
ng g c Custom

So now 4 files will automatically created in your project like as below

So first of all you need to implement ControlValueAccessor interface in custom component. After implementation you will have three methods in component.ts file as below:

JavaScript
import { Component, OnInit } from '@angular/core';
import { ControlValueAccessor } from '@angular/forms';

@Component({
  selector: 'app-custom',
  templateUrl: './custom.component.html',
  styleUrls: ['./custom.component.css']
})
export class CustomComponent implements ControlValueAccessor {

  constructor() { }
  
  onChange: any = () => {}
  onTouch: any = () => {}

  set value(val: string){}  

  writeValue(obj: any): void {
    throw new Error('Method not implemented.');
  }
  registerOnChange(fn: any): void {
    throw new Error('Method not implemented.');
  }
  registerOnTouched(fn: any): void {
    throw new Error('Method not implemented.');
  }

}

So first all of you need to understand these methods what functionality they will provide:

Now we can use ControlValueAccessor like as below code:

JavaScript
import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'app-custom',
  templateUrl: './custom.component.html',
  styleUrls: ['./custom.component.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: CustomComponent,
      multi: true
    }]
})

export class CustomComponent implements ControlValueAccessor {
  field= "";

  constructor() { }

  onChange: any = () => {}
  onTouch: any = () => {}

  // sets the value used by the ngModel of the element
  set value(val: string){
      this.field = val
      this.onChange(val)
      this.onTouch(val)
  }

  // This will will write the value to the view if the the value changes occur on the model programmatically
  writeValue(value: any){
    this.value = value
  }

  // When the value in the UI is changed, this method will invoke a callback function
  registerOnChange(fn: any){
    this.onChange = fn
  }

  // When the element is touched, this method will get called
  registerOnTouched(onTouched: Function) {
    this.onTouch = onTouched;
  }
}

Custom.Component.html

Code
<input [(ngModel)]="value"/>
<p>Internal data field:{{field}}</p>

App.componet.html

Code
<app-custom  [(ngModel)]="data"></app-custom>
<p>Data here:{{data}}</p>

App.componet.ts

JavaScript
import { Component, ViewChild } from '@angular/core';
import { CustomComponent } from './custom/custom.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  data:string='';
}

Let's run the project using following command:

JavaScript
ng serve

Summary

In this article, I have discussed about implementation of control value accessor in Angular.