When working with Angular forms, we often use standard input elements like and . But what if we need a custom input component that behaves like a native form control? This is where ControlValueAccessor comes in.
What is ControlValueAccessor ?
ControlValueAccessor is an Angular interface that allows custom form components to integrate with Angular’s form system. It acts as a bridge between the custom component and Angular Forms, ensuring the form can read and update its value correctly.
Without ControlValueAccessor, Angular Forms cannot automatically recognize a custom input component as a valid form control.
Why Use ControlValueAccessor?
By implementing ControlValueAccessor, we can:
✔ Make a custom component behave like a native input field.
✔ Ensure the component updates the form when the user types.
✔ Allow the form to update the component when its value changes externally.
✔ Support Angular’s built-in form validation and status tracking.
Example: Custom Input That Trims Spaces Automatically
Let’s say we need an input field that removes extra spaces whenever a user types.
Step 1: Create the Custom Input Component
import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-trimmed-input',
template: `<input [value]="value" (input)="onInput($event)" />`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TrimmedInputComponent),
multi: true
}
]
})
export class TrimmedInputComponent implements ControlValueAccessor {
value: string = '';
onChange: (value: string) => void = () => {};
onTouched: () => void = () => {};
// When user types, remove spaces and update value
onInput(event: Event) {
const inputValue = (event.target as HTMLInputElement).value.trim();
this.value = inputValue;
this.onChange(this.value);
}
// Update the component when the form control value changes
writeValue(value: string): void {
this.value = value ? value.trim() : '';
}
// Register function to handle value changes
registerOnChange(fn: any): void {
this.onChange = fn;
}
// Register function to handle input focus/touch events
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
}
Step 2: Use the Custom Component in a Form
import { Component } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
form = new FormGroup({
username: new FormControl('')
});
}
<form [formGroup]="form">
<app-trimmed-input formControlName="username"></app-trimmed-input>
</form>
How It Works
- The user types text into the field.
- Any extra spaces are automatically removed before updating the form control.
- The cleaned value is passed to the Angular form control using onChange().
- If the form updates externally, writeValue() ensures that the custom component reflects the latest value.
Other Use Cases for ControlValueAccessor
ControlValueAccessor is useful for creating:
• Number-only inputs (e.g., phone numbers, IDs).
• Inputs that automatically format text (e.g., uppercase conversion).
• Custom dropdowns or date pickers that work with Angular Forms.
Key Takeaways
• ControlValueAccessor enables custom components to work with Angular Forms.
• It ensures bidirectional communication between the component and the form control.
• Implementing it properly improves form validation, value tracking, and user experience.
Understanding ControlValueAccessor is crucial for any Angular developer building custom form components. By following the example above, you can create form controls that feel native and integrate seamlessly into your applications.
Top comments (0)