Détecter le changement de ngModel sur une balise de sélection (Angular 2)

97

J'essaie de détecter un changement ngModeldans une <select>balise. Dans Angular 1.x, nous pourrions résoudre ce problème avec un $watchon ngModelou en utilisant ngChange, mais je n'ai pas encore compris comment détecter un changement ngModeldans Angular 2.

Exemple complet : http://plnkr.co/edit/9c9oKH1tjDDb67zdKmr9?p=info

import {Component, View, Input, } from 'angular2/core';
import {FORM_DIRECTIVES} from 'angular2/common';

@Component({
    selector: 'my-dropdown'
})
@View({
    directives: [FORM_DIRECTIVES],
    template: `
        <select [ngModel]="selection" (ngModelChange)="onChange($event, selection)" >
            <option *ngFor="#option of options">{{option}}</option>
        </select>
        {{selection}}
    `
})
export class MyDropdown {
    @Input() options;

    selection = 'Dog';

    ngOnInit() {
        console.log('These were the options passed in: ' + this.options);
  }

  onChange(event) {
    if (this.selection === event) return;
    this.selection = event;
    console.log(this.selection);
  }

}

Comme nous pouvons le voir, si nous sélectionnons une valeur différente dans la liste déroulante, nos ngModelmodifications et l'expression interpolée dans la vue le reflètent.

Comment être informé de ce changement dans ma classe / mon contrôleur?

lux
la source
1
vous voudrez peut-être garder certains des commentaires supplémentaires sous contrôle; vous ne voulez pas que cette question soit signalée comme une diatribe déguisée. stackoverflow.com/help/dont-ask .
Claies

Réponses:

234

Mise à jour :

Séparez les liaisons d'événement et de propriété:

<select [ngModel]="selectedItem" (ngModelChange)="onChange($event)">
onChange(newValue) {
    console.log(newValue);
    this.selectedItem = newValue;  // don't forget to update the model here
    // ... do other stuff here ...
}

Vous pouvez également utiliser

<select [(ngModel)]="selectedItem" (ngModelChange)="onChange($event)">

et vous n'auriez pas à mettre à jour le modèle dans le gestionnaire d'événements, mais je crois que cela provoque le déclenchement de deux événements, donc c'est probablement moins efficace.


Ancienne réponse, avant de corriger un bogue dans la version bêta.1:

Créez une variable de modèle locale et attachez un (change)événement:

<select [(ngModel)]="selectedItem" #item (change)="onChange(item.value)">

plunker

Voir aussi Comment puis-je obtenir une nouvelle sélection dans "sélectionner" dans Angular 2?

Mark Rajcok
la source
1
Alors, à quoi ça sert ngModelsi je lie juste une nouvelle variable appelée item? N'est-ce pas l'intérêt de mettre ngModelentre parenthèses pour acquérir des écouteurs d'événements, alors pourquoi introduisons-nous une nouvelle variable?
lux
2
@lux, ouais bonne question. selectedItemsont nos données liées, que NgModel met à jour automatiquement pour nous, mais ... il ne nous informe pas des changements, ce qui est souvent suffisant (les vues et autres seront mises à jour), mais évidemment ce n'est pas assez bon pour votre cas d'utilisation. Dans l'autre question SO à laquelle j'ai fait référence, je décris comment j'ai essayé d'utiliser (ngModelChange)pour être notifié des modifications, mais elle est appelée deux fois pour chaque modification. Je ne sais pas si c'est un bug ou non. Quoi qu'il en soit, l'ajout d'une (change)liaison d'événement semble résoudre le problème.
Mark Rajcok
De plus, j'ai mis à jour le plunker qui montre qu'il selectedItemn'est pas mis à jour lors du onChange()déclenchement, il semble donc que nous ayons besoin de cette variable de modèle locale.
Mark Rajcok
@lux le #ou #itemdans notre cas est une référence locale . D'où pourquoi nous pouvons le faire item.change.
Mark Pieszak - Trilon.io
@lux, j'ai déjà décrit la façon de se connecter: se lier à l' ngModelChangeévénement personnalisé. Le problème est que <select>cet événement se déclenche deux fois pour chaque changement.
Mark Rajcok
12

Je suis tombé sur cette question et je vais soumettre ma réponse que j'ai utilisée et travaillé assez bien. J'avais un champ de recherche qui filtrait et un tableau d'objets et sur mon champ de recherche, j'ai utilisé le(ngModelChange)="onChange($event)"

dans mon .html

<input type="text" [(ngModel)]="searchText" (ngModelChange)="reSearch(newValue)" placeholder="Search">

puis dans mon component.ts

reSearch(newValue: string) {
    //this.searchText would equal the new value
    //handle my filtering with the new value
}
Logan H
la source
5
Juste FYI, lors de la liaison à ngModelChange, $eventn'est pas un événement DOM . Il s'agit plutôt de la valeur actuelle de l'élément de formulaire, qui est une chaîne pour un élément d'entrée.
Mark Rajcok
@MarkRajcok pouvez-vous s'il vous plaît me diriger vers la documentation à ce sujet, afin que je puisse partager avec le reste de mon équipe de développement?
Neil S
1
@NeilS, le plus proche est angular.io/docs/ts/latest/guide/template-syntax.html#!#ngModel
Mark Rajcok