Update in January 2017: This article has been updated for the final API of Angular 2.x.

To make your components compatible with both template-driven (declarative) and reactive forms, you need to implement the ControlValueAccessor interface. Angular 2 relies on the methods defined here to read from and write to the underlying control.

These controls integrate seamlessly with ngModel or ngControl. For instance, the snippet below shows a custom date-control being bound to a variable named date through ngModel:

<!-- Deklaratives (template-driven) Forms-Handling 
<date-control [(ngModel)]="date"></date-control>

Alternatively, reactive forms can wire up the same component by attaching the date-control to a predefined Control object via formControlName. The framework then looks for that named FormControl inside the FormGroup supplied with formGroup:

<!-- Imperatives Forms-Handling -->
<form [formGroup]="filter">   
    <date-control formControlName="date"></date-control>
    [...]
</form>

The component supplies the ControlGroup and the Control:

@Component({
    selector: 'flight-search',  
    template: require('./flight-search.component.html'),
    directives: [DateControlComponent]
})
export class FlightSearchImpComponent {

    public filter: FormGroup;

    constructor(private fb: FormBuilder) {

        this.filter = fb.group({
           date: ['2016-05-01']
        });
    }

    [...]
}

Below we walk through the steps for implementing ControlValueAccessor. The complete sample code is available here.

Understanding ControlValueAccessor

The ControlValueAccessor interface exposes three methods that bridge the control's state with the form's object graph that Angular maintains:

//
// From the Angular2-Sources
//
export interface ControlValueAccessor {
    writeValue(obj: any): void;
    registerOnChange(fn: any): void;
    registerOnTouched(fn: any): void;
}

When the framework needs to set a value, it calls writeValue. Angular also needs to be notified of user interactions, so it provides callbacks via registerOnChange and registerOnTouched. The first callback fires when the user alters the value; the second signals that the field has been focused at some point.

Putting ControlValueAccessor into Practice

The following code illustrates a concrete implementation of ControlValueAccessor. It defines a lightweight component for date entry. The splitDate method separates a date into its constituent parts, which the (not shown) template then exposes for editing. Conversely, apply recombines those parts back into a complete date.

import { Component } from '@angular/core';
import { ControlValueAccessor, NgControl } from '@angular/forms';

@Component({
    selector: 'date-control',
    template: require('./date-control.component.html')
})
export class DateControlComponent 
                    implements ControlValueAccessor {

    day: number;
    month: number;
    year: number;
    hour: number;
    minute: number;

    constructor(private c: NgControl) {
        c.valueAccessor = this;
    }

    writeValue(value: any) {
        this.splitDate(value);
    }

    onChange = (_) => {};
    onTouched = () => {};

    registerOnChange(fn): void { this.onChange = fn; }
    registerOnTouched(fn): void { this.onTouched = fn; }

    splitDate(dateString) {
      var date = new Date(dateString); 

      this.day = date.getDate();
      this.month = date.getMonth() + 1;
      this.year = date.getFullYear();
      this.hour = date.getHours();
      this.minute = date.getMinutes();
    }

    apply() {

        var date = new Date();
        date.setDate(this.day);
        date.setMonth(this.month - 1);
        date.setFullYear(this.year);
        date.setHours(this.hour);
        date.setMinutes(this.minute);
        date.setSeconds(0);
        date.setMilliseconds(0);

        this.onChange(date.toISOString());
        this.onTouched();
    }

}

To hook into Angular 2's form handling, the component implements ControlValueAccessor and injects the current NgControl. This instance represents the control in the form's object graph. Angular assigns the component itself to the ValueAccessor property, meaning the component acts as its own value accessor.

Within writeValue, the component receives new values from the framework and forwards them to splitDate. Meanwhile, registerOnChange and registerOnTouched store the callbacks supplied by Angular into onChange and onTouched respectively.

When the user modifies the date, the template triggers apply. This method reassembles the date pieces and hands the result to Angular through onChange. It also invokes onTouched to ensure the touched state is properly tracked.