‘ControlValueAccessor‘ is an interface in Angular that is used to create custom form controls that can work seamlessly with Angular’s form handling methods like ‘FormControl‘, ‘FormGroup‘, or ‘FormArray‘. It acts as a bridge between Angular’s form handling API and the custom form control, providing a way to communicate value change events or value retrieval between them.
The ‘ControlValueAccessor‘ interface contains four methods that must be implemented to create a custom form control. These methods are:
1. ‘writeValue(obj: any): void‘: This method is used to write a new value from the form model to the view. It is called when the value of the form control changes programmatically or when the initial form value is set.
2. ‘registerOnChange(fn: any): void‘: This method is called when a control value changes in the view. It is used to register a handler function that will be called when the value in the view changes. Usually, this is where you emit a custom event with the new value, and Angular will update the form model accordingly.
3. ‘registerOnTouched(fn: any): void‘: This method is called when the control receives a touch event. It is used to register a handler function that will be called when the control receives a touch event. This is useful for handling validation and displaying error messages.
4. ‘setDisabledState(isDisabled: boolean): void‘: This method is called by Angular to enable or disable the control. It is used to update the state of the control based on the form or control validator’s state.
To create a custom form control using ‘ControlValueAccessor‘, you must take the following steps:
1. Create a new Angular component that will be your custom control.
2. Implement the ‘ControlValueAccessor‘ interface in your component. This involves implementing the four methods described above.
3. Register your custom control as an Angular provider using the ‘NG_VALUE_ACCESSOR‘ token. This tells Angular that your component will be used as a form control and integrate with Angular’s built-in form handling.
Here’s a simple example of a custom form control that takes a number as input and displays it as a percentage:
import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-percentage-input',
template: `
<input type="number" [value]="value" (input)="onInput($event)" (blur)="onTouched()" [disabled]="isDisabled">
<span>%</span>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => PercentageInputComponent),
multi: true
}
]
})
export class PercentageInputComponent implements ControlValueAccessor {
private isDisabled = false;
onChange: any = () => {};
onTouched: any = () => {};
value: number;
writeValue(value: number): void {
this.value = value;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState(isDisabled: boolean): void {
this.isDisabled = isDisabled;
}
onInput(event: any): void {
this.value = event.target.value;
this.onChange(this.value);
}
}
This custom form control can be used in any Angular form, both template-driven and reactive forms, and it will work just like built-in form controls.