All topics
Formsadvanced

ControlValueAccessor for Custom Form Controls

Explain how ControlValueAccessor lets a custom component integrate seamlessly with ngModel and reactive forms directives.

ControlValueAccessor is the interface that bridges Angular's forms API to an arbitrary component — it's what lets [(ngModel)] and formControlName work on native <input> elements, and it's exactly what you implement when you want a custom component (a star rating widget, a custom date picker, a toggle switch) to be usable inside a form exactly like a native input, with full support for validation, disabled state, and value binding.

It's like a universal remote control that speaks the same infrared protocol as every native remote in the house — because it 'speaks the same language' (implements the same interface), the TV can't tell it apart from an original manufacturer remote.

Key Concepts

1
The interface requires four methods: writeValue(value) (called by Angular to push a new value into the component, e.g., when patchValue() is called externally), registerOnChange(fn) (Angular gives you a callback to invoke whenever the user changes the value internally, which is how your component reports changes back out to the form), registerOnTouched(fn) (similarly, a callback to invoke when the control should be marked as touched, typically on blur), and setDisabledState(isDisabled) (called when the control's disabled state changes, letting your component reflect that visually/functionally).
writeValue(value)patchValue()registerOnChange(fn)registerOnTouched(fn)setDisabledState(isDisabled)
2
Registering the component as a value accessor requires providing NG_VALUE_ACCESSOR (a multi-provider token, tying directly back to the Multi-providers topic) with useExisting: forwardRef(() => YourComponent) — the forwardRef is necessary because the class is referencing itself in its own decorator metadata before the class declaration has fully finished evaluating.
NG_VALUE_ACCESSORuseExisting: forwardRef(() => YourComponent)forwardRef
3
Modern Angular (17+) also allows implementing this more simply by having the component provide itself via hostDirectives composition patterns or newer signal-forms-adjacent approaches in some cases, but the classic ControlValueAccessor interface remains the standard, broadly-supported mechanism, and interviewers still expect you to know all four methods and the NG_VALUE_ACCESSOR registration pattern by heart, since it's a frequent "build a custom form control" take-home or live-coding exercise.
hostDirectivesControlValueAccessorNG_VALUE_ACCESSOR