ControlValueAccessor (CVA) is Angular’s official bridge between custom components and Angular Forms. It lets your component behave like a real form control (ngModel, formControl, formControlName) with validation, touched/dirty state, and disabled handling—unlike custom two-way binding which only syncs values and breaks form integration.
What Is ControlValueAccessor in Angular and Why Is It Better Than Custom Two-Way Binding?
Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.
Core ideaControlValueAccessor (CVA) is the interface that tells Angular Forms how to write a value into your component and how your component reports changes back. If you want a custom input component to work with ngModel, formControl, or formControlName, you must implement CVA.
Why not just use custom two-way binding?
Two-way binding like [(value)] only synchronizes a value. It does not integrate with Angular Forms, so you lose validation, touched/dirty states, disabled state, and form-level APIs. CVA plugs your component into the entire forms ecosystem.
Capability | Custom [(value)] binding | ControlValueAccessor |
|---|---|---|
Works with Reactive Forms / ngModel | ❌ No | ✅ Yes |
Supports validators | ❌ No | ✅ Yes |
Tracks touched / dirty / pristine | ❌ No | ✅ Yes |
Supports disabled state | ❌ Manual hacks | ✅ Built-in via setDisabledState |
Integrates with FormGroup / FormControl | ❌ No | ✅ Yes |
Minimal CVA implementation
A CVA has four responsibilities:
• writeValue: Angular → component
• registerOnChange: component → Angular
• registerOnTouched: mark as touched
• setDisabledState: handle disabled
import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-rating',
template: `
<button *ngFor="let n of [1,2,3,4,5]" (click)="set(n)" [disabled]="disabled">
{{ n }}
</button>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RatingComponent),
multi: true
}
]
})
export class RatingComponent implements ControlValueAccessor {
value = 0;
disabled = false;
private onChange = (v: number) => {};
private onTouched = () => {};
writeValue(v: number): void {
this.value = v ?? 0;
}
registerOnChange(fn: (v: number) => void): void {
this.onChange = fn;
}
registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
}
set(v: number) {
if (this.disabled) return;
this.value = v;
this.onChange(v); // notify Angular Forms
this.onTouched(); // mark as touched
}
}
Using it like a real form control
<form [formGroup]="form">
<app-rating formControlName="rating"></app-rating>
</form>
Why this is strictly better than custom two-way binding
With CVA, your component becomes a first-class Angular form control. It participates in validation, form submission, reset, disabled state propagation, and form-level state tracking. Two-way binding only moves a value around—it does not integrate into the forms system.
Real-world requirement | Without CVA | With CVA |
|---|---|---|
Disable the whole form | ❌ You must wire every input manually | ✅ setDisabledState is called automatically |
Mark control as touched | ❌ Manual hacks | ✅ Angular handles it |
Show validation errors | ❌ Not integrated | ✅ Works via FormControl |
Reset the form | ❌ Manual reset logic | ✅ Angular resets automatically |
Senior-level pitfalls
• Forgetting to call onTouched() (control never becomes touched)
• Not implementing setDisabledState (disabled forms don’t work)
• Mutating internal state without calling onChange
• Using custom two-way binding for components that should be form controls
Interview summaryControlValueAccessor is Angular’s official way to make a custom component behave like a real form control. It integrates with Reactive Forms and ngModel, supports validation, touched/dirty state, disabled handling, and form APIs. Custom two-way binding only syncs a value and does not integrate with Angular Forms, which makes it unsuitable for serious form components.