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.