title: How Can I Subscribe to FormControl Value Changes In an Angular ControlValueAccessor Directive
body: <p>I have a Directive in Angular that implements ControlValueAccessor. The directive seems to be working aside from getting values set in FormControl.setValue(). How do I get that value update in the directive?</p>
  
  <p>Here's my Directive</p>
  
  <pre><code>import {
    Directive,
    ElementRef,
    EventEmitter,
    forwardRef,
    HostListener,
    Input,
    Output,
    Renderer2
  } from '@angular/core';
  import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
  import {CurrencyPipe} from '@angular/common';
  
  @Directive({
    selector: '[currency-input]',
    providers: [
      {
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() =&gt; CurrencyInputDirective),
        multi: true
      }
    ]
  })
  export class CurrencyInputDirective implements ControlValueAccessor {
  
    // TODO: Allow null value
    _currencyString: string = '';
  
    @Input() ciDecimals = 2;
    @Input() ciCurrencyCode = 'USD';
    @Input() ciMaximumAmount = 10000;
  
    // Pass true if using formControl or formControlName
    @Input() ciModelDrivenForm = false;
    @Output() ciExceededMax: EventEmitter&lt;any&gt; = new EventEmitter();
  
    onChangeCallback = (_: any) =&gt; {};
    onTouchedCallback = () =&gt; {};
  
    @HostListener('onNgModelChange') onNgModelChange() {
      // Never runs
      console.log("in ng model change");
    }
  
    @HostListener('input', ['$event']) onInput(value: any) {
      // Never runs
      console.log("in input");
    }
  
    @HostListener('blur', []) onBlur() {
      this.onTouchedCallback();
    }
  
    @HostListener('focus', []) onFocus() {
      this.onTouchedCallback();
    }
  
    @HostListener('keydown', ['$event']) onKeyDown(e: KeyboardEvent) {
      switch (e.key) {
        case 'Backspace':
          this.handleBackspaceKeyPress(e);
          break;
        default:
          if (isNaN(+e.key)) {
            e.preventDefault();
          } else {
            this.handleNumericKeyPress(e);
          }
          break;
      }
    }
  
    constructor (
      private _renderer: Renderer2,
      private _elementRef: ElementRef,
      private _currencyPipe: CurrencyPipe
    ) {}
  
    writeValue(value: any) {
      this._renderer.setProperty(this._elementRef.nativeElement, 'value', this.buildElementValue());
      this.onChangeCallback(this.buildControlValue());
    }
  
    registerOnChange(fn: any) {
      this.onChangeCallback = fn;
    }
  
    registerOnTouched(fn: any) {
      this.onTouchedCallback = fn;
    }
  
    setDisabledState(isDisabled: boolean) {
      this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
    }
  
    private handleBackspaceKeyPress(e: KeyboardEvent) {
      e.preventDefault();
      // Remove one digit
      if (this._currencyString.length &gt; 0) {
        this._currencyString = this._currencyString.slice(0, this._currencyString.length - 1);
      }
  
      this.writeValue(this._currencyString);
    }
  
    private handleNumericKeyPress(e: KeyboardEvent) {
      e.preventDefault();
  
      const newCurrencyString = this._currencyString + e.key;
      const currencyValue: number = this.convertCurrencyStringToCurrencyValue(newCurrencyString);
  
      if (currencyValue &gt; this.ciMaximumAmount) {
        setTimeout(() =&gt; {
          this.ciExceededMax.emit({ amount: currencyValue, maxAmount: this.ciMaximumAmount });
        }, 1);
        return;
      }
  
      this._currencyString = newCurrencyString;
      this.writeValue(this._currencyString);
    }
  
    private buildElementValue() {
      const currencyDecimals = '1.' + this.ciDecimals + '-' + this.ciDecimals;
  
      const retVal: string = !this._currencyString ? null : this._currencyPipe.transform(
        this.convertCurrencyStringToCurrencyValue(this._currencyString),
        this.ciCurrencyCode,
        'symbol',
        currencyDecimals);
      return retVal ? retVal : this._currencyPipe.transform(0, this.ciCurrencyCode, 'symbol', currencyDecimals);
    }
  
    private buildControlValue() {
      return this.convertCurrencyStringToCurrencyValue(this._currencyString);
    }
  
    private convertCurrencyValueToCurrencyString(currencyValue: number): string {
      return currencyValue.toString().replace(/[^0-9]/g, '');
    }
  
    private convertCurrencyStringToCurrencyValue(currencyString: String): number {
      const strippedValue: string = currencyString.replace(/[^0-9]/g, '');
  
      if (strippedValue.length === 0) {
        return 0;
      }
      const parsedInt: number = parseInt(strippedValue, 10);
      return parsedInt / Math.pow(10, this.ciDecimals);
    }
  }
  
  </code></pre>
  
  <p>Here's my setValue()</p>
  
  <pre><code>myForm.get('myField').setValue(5.00);
  </code></pre>