web-dev-qa-db-fra.com

Comment observer un événement touché sur Angular 2 NgForm?

Il est possible de souscrire un rappel à une propriété observable NgForm de valueChanges afin de réagir aux modifications des valeurs des contrôles du formulaire.

De la même manière, j'ai besoin de réagir à l'événement de l'utilisateur touchant l'un des contrôles de formulaire.

Cette classe semble définir l'observable valueChanges et la propriété touched est définie comme un booléen.

Existe-t-il un moyen de réagir à l'événement "contrôle touché"? 

14
Chedy2149

Il n'y a pas de moyen direct fourni par ng2 pour réagir à un événement touché. Il utilise ( input ) event pour déclencher les événements valueChanges et ( blur ) pour définir touché/inaltéré propriété de AbstractControl ..__ devez souscrire manuellement à l'événement souhaité dans le modèle et le gérer dans votre classe de composants.

8
Valikhan Akhmedov

Vous pouvez étendre la classe FormControl par défaut et ajouter la méthode markAsTouched qui appellera la méthode native, plus votre effet secondaire.

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);
  }
}
9
Eggy

Si votre problème ressemblait beaucoup au mien, j'essayais de marquer un champ comme étant touché dans un composant, puis de répondre à cela dans un autre. J'ai eu accès à la AbstractControl pour ce champ. La façon dont je me débrouillais était

field.markAsTouched();
(field.valueChanges as EventEmitter<any>).emit(field.value);

Et puis je viens de souscrire à valueChanges dans mon autre composant. À noter: field.valueChanges est exporté en tant qu'observable, mais au moment de l'exécution, il s'agit d'une EventEmitter, ce qui en fait une solution moins que belle. L’autre limite de cette situation serait évidemment le fait que vous souscrivez à beaucoup plus que le simple état touché.

1
Ethan Stan Del