[Angular] Create a ng-true-value and ng-false-value in Angular by controlValueAccessor

If you're coming from AngularJS (v1.x) you probably remember the ng-true-value and ng-false-value directive which allowed to map custom boolean values like "yes" or "no" or whatever other value you had, onto your HTML form. In this lesson we're going to implement our own trueFalseValue directive for Angular, by directly hooking into Angular's form API. A nice occasion to learn about the ControlValueAccessor interface.

import { Directive, Input, ElementRef, Renderer2, HostListener, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Directive({
  selector: 'input[type=checkbox][trueFalseValue]',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => TrueFalseValueDirective),
      multi: true
    }
  ]
})
export class TrueFalseValueDirective implements ControlValueAccessor {
  @Input() trueValue = true;
  @Input() falseValue = false;
  private propagateChange = (_: any) => { };

  constructor(private elementRef: ElementRef, private renderer: Renderer2) {
  }

  @HostListener('change', ['$event'])
  onHostChange(ev) {
    this.propagateChange(ev.target.checked ? this.trueValue : this.falseValue);
  }

  writeValue(obj: any): void {
    // model -> view
    if (obj === this.trueValue) {
      // this.elementRef.nativeElement.checked = true;
      this.renderer.setProperty(this.elementRef.nativeElement, 'checked', true);
    } else {
      this.renderer.setProperty(this.elementRef.nativeElement, 'checked', false);
    }
  }
  registerOnChange(fn: any): void {
    this.propagateChange = fn;
  }
  registerOnTouched(fn: any): void {
  }
  setDisabledState?(isDisabled: boolean): void {
  }
}

How to use:

      <input type="checkbox" formControlName="lovingAngular"
        trueFalseValue
        trueValue="yes" falseValue="nope"
        > loving Angular?