Control value accessor in Angular

Control value accessor in Angular

·

2 min read

The ControlValueAccessor interface offers a collection of functions that enable Angular forms to communicate with native DOM elements. In essence, it serves as a vital link between Angular Form APIs and DOM elements.

interface ControlValueAccessor {
  writeValue(obj: any): void
  registerOnChange(fn: any): void
  registerOnTouched(fn: any): void
  setDisabledState(isDisabled: boolean)?: void
}

To illustrate where ControlValueAccessor can be useful, let's consider an application that involves forms with custom build select boxes, checkboxes or date fields. In such a scenario, the traditional approach would be to rely on component interaction methods like @Input and @Output to handle these elements. However, using ControlValueAccessor provides a more streamlined solution by enabling direct communication between the Angular Form APIs and the DOM elements, eliminating the need for intermediary component communication.

The following code snippet illustrates a component that extends the ControlValueAccessor interface:


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

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

export class MyElementComponent implements OnInit, ControlValueAccessor {

  value: string = '';
  onChange: (value: string) => void;
  onTouched: () => void
  constructor() {}
// We have to define the following functions to use controlValue Accessor
  writeValue(obj: any): void {
    // assigning the value from the control value
    this.value = obj;
  }
  registerOnChange(fn: any): void {
    this.onChange = fn;
    // this function have to call from the code
    // whenever the value in the code is updating
    // example: this.onChange(newValue)
  }
  registerOnTouched(fn: any): void {
    this.onTouched = fn;
    // this function have to call from the code 
    // to update the touched field in the control
    // similar to registerOnChange Function
    // example: this.onTouched()

  }
  setDisabledState(isDisabled: boolean): void {
    // this will get called if the controll 
    // is being disabled
  }

  ngOnInit(): void {}
}
<!-- parent component -->
<app-my-element 
    formControlName="your form control name goes here">
</app-my-element>

As shown in the above code, it is possible to bind a form control directly to the MyElementComponent, allows any value changes made in the component to be automatically reflected in the form control.

And That's about it!

Thanks for reading and until the next time.