0 day streak
javascript / intermediate
Snippet

Implementing the ControlValueAccessor Interface for Custom Form Controls

By implementing the ControlValueAccessor interface, a class contracts with Angular Forms to act as a bridge between the DOM and the reactive form model, enabling polymorphic integration into form bindings.

snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-counter-input',
standalone: true,
template: `<button (click)="increment()">+1 (Value: {{ value }})</button>`,
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CounterInputComponent),
multi: true
}]
})
export class CounterInputComponent implements ControlValueAccessor {
value = 0;
private onChange = (val: number) => {};
private onTouched = () => {};
writeValue(val: number): void { this.value = val ?? 0; }
registerOnChange(fn: (val: number) => void): void { this.onChange = fn; }
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
increment(): void {
this.value++;
this.onChange(this.value);
this.onTouched();
}
}
angular
Breakdown
1
export class CounterInputComponent implements ControlValueAccessor {
Explicitly implements the interface contract required for custom form control behavior.
2
writeValue(val: number): void { this.value = val ?? 0; }
Receives values programmatically from the Angular form API and updates internal component state.
3
registerOnChange(fn: (val: number) => void): void { this.onChange = fn; }
Registers a callback function to notify the Angular forms system whenever the user updates the internal value.