web-dev-qa-db-fra.com

Manière correcte de s'abonner à valueChanges in Angular 2

Je bricole avec des formes réactives et une abonnement valueChanges dans Angular 2. Je ne comprends pas très bien pourquoi certaines formes d’abonnement semblent interdites.

this.form.get('name').valueChanges /* <- doesn't work */
  .do(changes => {
    console.log('name has changed:', changes)
    });
  .subscribe();

this.form.get('title').valueChanges.subscribe( /* <- does work */
  changes => console.log('title has changed:', changes)
);

Ce pilote reproduit le problème (ouvrez la console DevTools pour voir l'erreur):

ZoneAwareError {stack: "Erreur: Non capturé (promis): TypeError: Ne peut pas se…g.com/[email protected]/dist/zone.js: 349: 25) []", message: "Uncaught (in promesse): TypeError: Impossible de définir le fichier… ore.umd.js: 8486: 93) ↵ dans Array.forEach (native) ", originalStack:" Erreur: Non capturé (dans la promesse): TypeError: Impossible de se… ps: // unpkg .com/zone.js @ 0.7.5/dist/zone.js: 349: 25) ", zoneAwareStack:" Erreur: Non capturé (promis): TypeError: Impossible de se se situer.com/[email protected] /dist/zone.js:349:25) [] ", nom:" Erreur "…}

Le premier motif (avec do) n'est-il pas illégal?

6
user776686

Cela a fait fonctionner votre plunker:

  1. ajouter cette déclaration d'importation dans app.ts
  import 'rxjs/add/operator/do';
  1. Supprimer le point-virgule après l'instruction .do

.do (changes => { console.log ('nom a changé:', modifications) })

App.ts complet modifié 

import {Component, NgModule, OnInit} from '@angular/core'
import {BrowserModule } from '@angular/platform-browser'
import { FormGroup, FormBuilder, Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/do';

@Component({
  selector: 'my-app',
  template: `
    <form novalidate [formGroup]="form">
      <div>
        <select type="text" class="form-control" name="title" formControlName="title">
          <option *ngFor="let title of titles" value="{{title}}">{{title}}</option>
        </select>
      </div>
      <div>
        <input type="text" class="form-control" name="name" formControlName="name">
      </div>
      <fieldset formGroupName="address">
        <legend>Address</legend>
        <input type="text" class="form-control" name="street" formControlName="street">
        <input type="text" class="form-control" name="city" formControlName="city">
      </fieldset>
    </form>
  `,
})
export class App implements OnInit {
  private form: FormGroup;
  private titles: string[] =  ['Mr', 'Mrs', 'Ms'];

  constructor(private fb: FormBuilder){

  }
  ngOnInit() {
    this.form = this.fb.group({
      title: 'Mr',
      name: '',
      address: this.fb.group({
        street: '',
        city: ''
      })
    });

    this.form.get('name').valueChanges
      .do(changes => {
        console.log('name has changed:', changes)
        })
      .subscribe();

    this.form.get('title').valueChanges.subscribe(
      changes => console.log('title has changed:', changes)
    );

    this.form.get('address').valueChanges.subscribe(
      changes => console.log('address has changed:', changes)
    );  
  }
}

@NgModule({
  imports: [ BrowserModule, FormsModule, ReactiveFormsModule ],
  declarations: [ App ],
  bootstrap: [ App ]
})
export class AppModule {}

Une autre solution consisterait à utiliser l'événement "ngModelChange"

Modifiez cela dans votre modèle:

 <input type="text" class="form-control" (ngModelChange)="doNameChange($event)" name="name" formControlName="name">

Dans votre composant, vous gérez alors votre événement de changement:

doNameChange(event: any){
   alert("change")
}
2
Karl

un des moyens est:

debounceTime fera un abonnement après des millisecondes données. Si non requis, ignorer.

distinctUntilChanged forcera la souscription uniquement lors du changement de valeur réelle.

 this.form.controls['form_control_name']
            .valueChanges
            .debounceTime(MilliSeconds)
            .distinctUntilChanged()
            .subscribe(val => {

              });
2

J'avais aussi des problèmes avec ça.

Je voulais faire debounceTime dans mon cas, donc cela ne répondait pas à mes besoins.

J'ai en fait oublié de m'inscrire!

Mais j’ai pu obtenir des changements de valeur à activer de cette façon aussi:

this.form.get('name').valueChanges.forEach(
    (value) => {console.log(value);} )

Provenant d'ici dans le Angular docs: hero-detail-component.ts

0
JGFMK