Creating a custom Angular form control
Advanced applications and custom libraries often require to create custom form controls that one can use in with ngModel and form controls. We are going to describe the journey from a simple component to a re-usable custom form control.
Imagine a nicely designed tags component. UX is great, it looks good. Here is how it looks like:
And here is how developers use it:
However, the standard way in Angular to handle user inputs is through forms, being template driven or reactive. As it is, we can not use our tags component in a regular Angular form or with a standalone ngModel binding. We can workaround that but the most straight-forward way to make our component easier to use is to make it a real Custom Value Accessor. At the end of our journey, we will be able to use our component as follows:
The simple tags implementation
Let’s start by having a look at our tags component: the user can enter several text values that are then stored in an array of strings and returned as output by the component.
At the moment, you can use it like that:
Make our tags component a control value accessor
In order to make this component a control value accessor, the first thing to do is to declare our component as being usable along with the Angular forms API. To do that, we add a provider to the Component decorator:
A control value accessor is a bridge between the Angular forms API and a component: it interacts with the rest of your Angular application through the ngModel or the formControl or the formControlName directives. When those directives are bound to an element, Angular expects this element to implement a specific interface: ControlValueAccessor. As its name indicates, your component controls the access to the value:
- Angular gives the value to your component so that your component can do internal logic: changing variables, manipulating the DOM etc. The value is given through the writeValue method that your component implements.
- Angular gives two callbacks to your component: onTouched and onChange. Your component should store those two callbacks and call them whenever the value has been changed (onChange) and when the control has been touched (onTouched). Those two callbacks are given through the registerOnChange and registerOnTouched methods.
- Your component is free to implement the setDisabled method. Angular will use this method to enable or disable your component.
The next step is to implement the necessary methods: they are declared in the ControlValueAccessor interface.
This is how the tags component looks like now:
Our component is now a control value accessor and can now be used as a standard form control or with ngModel.