How to observe touched event on Angular 2 NgForm?

Chedy2149 picture Chedy2149 · Dec 26, 2016 · Viewed 16.9k times · Source

It is possible to subscribe a callback to an NgForm's valueChanges observable property in order to react to changes in the values of the controls of the form.

I need, in the same fashion, to react to the event of the user touching one of the form controls.

This class seem to define the valueChanges Observable and the touched property is defined as a boolean.

Is there a way to to react to the "control touched" event?

Answer

Eggy picture Eggy · Apr 13, 2017

You can extend default FormControl class, and add markAsTouched method that will call native method, plus your side effect.

import { Injectable } from '@angular/core';
import { FormControl, AsyncValidatorFn, ValidatorFn } from '@angular/forms';
import { Subscription, Subject, Observable } from 'rxjs';

export class ExtendedFormControl extends FormControl {
  statusChanges$: Subscription;
  touchedChanges: Subject<boolean> = new Subject<boolean>();

  constructor(
    formState: Object,
    validator: ValidatorFn | ValidatorFn[] = null,
    asyncValidator: AsyncValidatorFn | AsyncValidatorFn[] = null
  ) {
    super(formState, validator, asyncValidator);

    this.statusChanges$ = Observable.merge(
      this.valueChanges,
      this.touchedChanges.distinctUntilChanged()
    ).subscribe(() => {
      console.log('new value or field was touched');
    });
  }

  markAsTouched({ onlySelf }: { onlySelf?: boolean } = {}): void {
    super.markAsTouched({ onlySelf });

    this.touchedChanges.next(true);
  }
}