Custom Form Components Angular4

  • You are building complex forms that have custom validators, styling, and behaviours that make using plain <input> tags all over the place unsuitable
  • You therefore want custom form input controls that bind to ngModel and have complex validation behaviour
  • You dislike FormBuiler, FormControl and FormGroup and find that they reduce maintainability and understandability of the code: you want to define your forms in your template only, not in code

Standard form element usage:

<input type=”text” [(ngModel)]=”myValue” required />

Our custom form element component usage:

Implementing our form control

<form-text [(ngModel)]=”myValue” required />

import {Component, Input} from ‘@angular/core’;

import { 
} from ‘@angular/forms’;

 selector: ‘form-text’,
 template: `
 <input type=”text” [(ngModel)]=”value” />
 providers: [
 {provide: NG_VALUE_ACCESSOR, useExisting: FormTextComponent, multi: true}
export class FormTextComponent {}

  • We are telling the dependency injector that we implement ControlValueAccessor, (NG_VALUE_ACCESSOR), but we do not actually implement it. We have to add implementations for those methods and abstract them into something we can share amongst all form components.
  • So we need to remedy these problems before we can move on. The first thing we need to do is implement the ControlValueAccessor interface. But we are going to be implementing this interface on all of our input elements.

Common ValueAccessor abstract base

interface ControlValueAccessor {

writeValue(obj: any): void

registerOnChange(fn: any): void

registerOnTouched(fn: any): void

setDisabledState(isDisabled: boolean): void


import {ControlValueAccessor} from ‘@angular/forms’;

export class ValueAccessorBase<T> implements ControlValueAccessor { 
 private innerValue: T;

private changed = new Array<(value: T) => void>();
 private touched = new Array<() => void>();

get value(): T {
 return this.innerValue;

set value(value: T) {
 if (this.innerValue !== value) {
 this.innerValue = value;
 this.changed.forEach(f => f(value));

touch() {
 this.touched.forEach(f => f());

writeValue(value: T) {
 this.innerValue = value;

registerOnChange(fn: (value: T) => void) {

registerOnTouched(fn: () => void) {


  • Implements the Control Value Accessor pattern from Angular

ElementBase<T> extends ValueAccessor<T>

  • Provides observable values to its parent about its validity state
  • Provides a validate method which can also be used in the control and which works off of validators injected through hierarchical dependency injection (eg. a required or minlength directive).

Let’s break down the ElementBase<T> implementation itself:

import {NgModel} from '@angular/forms';

import {Observable} from 'rxjs';

import {ValueAccessorBase} from './value-accessor';

export abstract class ElementBase<T> extends ValueAccessorBase<T> { 
 protected abstract model: NgModel;

// we will ultimately get these arguments from @Inject on the derived class
 constructor(private validators: ValidatorArray,
 private asyncValidators: AsyncValidatorArray,
 ) {

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.