DEV Community

Rawan Tarek
Rawan Tarek

Posted on

ControlValueAccessor | Angular

Image description

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;

  }

} 
Enter fullscreen mode Exit fullscreen mode

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> 
Enter fullscreen mode Exit fullscreen mode

How It Works

  1. The user types text into the field.
  2. Any extra spaces are automatically removed before updating the form control.
  3. The cleaned value is passed to the Angular form control using onChange().
  4. 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.

Heroku

Amplify your impact where it matters most — building exceptional apps.

Leave the infrastructure headaches to us, while you focus on pushing boundaries, realizing your vision, and making a lasting impression on your users.

Get Started

Top comments (0)

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay