Erkennen Sie die Änderung von ngModel an einem ausgewählten Tag (Winkel 2).

97

Ich versuche, eine Änderung ngModelin einem <select>Tag zu erkennen. In Angular 1.x könnten lösen wir dies mit einem $watchauf ngModel, oder durch die Verwendung ngChange, aber ich habe noch zu verstehen , wie eine Änderung zu erfassen , ngModelin Angular 2.

Vollständiges Beispiel : 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);
  }

}

Wie wir sehen können, spiegeln unsere ngModelÄnderungen und der interpolierte Ausdruck in der Ansicht dies wider , wenn wir einen anderen Wert aus der Dropdown-Liste auswählen .

Wie werde ich über diese Änderung in meiner Klasse / meinem Controller informiert?

Lux
quelle
1
Vielleicht möchten Sie einige der zusätzlichen Kommentare in Schach halten. Sie möchten nicht, dass diese Frage als Verkleidung gekennzeichnet wird. stackoverflow.com/help/dont-ask .
Claies

Antworten:

234

Update :

Trennen Sie die Ereignis- und Eigenschaftsbindungen:

<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 ...
}

Sie könnten auch verwenden

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

und dann müssten Sie das Modell im Ereignishandler nicht aktualisieren, aber ich glaube, dies führt dazu, dass zwei Ereignisse ausgelöst werden, sodass es wahrscheinlich weniger effizient ist.


Alte Antwort, bevor sie einen Fehler in Beta.1 behoben haben:

Erstellen Sie eine lokale Vorlagenvariable und fügen Sie ein (change)Ereignis hinzu:

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

plunker

Siehe auch Wie kann ich in "Auswählen" in Winkel 2 eine neue Auswahl erhalten?

Mark Rajcok
quelle
1
Was bringt es also, ngModelwenn ich nur eine neue Variable namens itembinde? Ist es nicht sinnvoll, ngModelin Klammern zu setzen, um Ereignis-Listener zu erhalten? Warum führen wir also eine neue Variable ein?
Lux
2
@lux, ja gute frage. selectedItemsind unsere gebundenen Daten, die NgModel automatisch für uns aktualisiert, aber ... es benachrichtigt uns nicht über Änderungen, was oft gut genug ist (Ansichten und solche werden aktualisiert), aber offensichtlich ist dies nicht gut genug für Ihren Anwendungsfall. In der anderen SO-Frage, auf die ich verwiesen habe, beschreibe ich, wie ich versucht habe (ngModelChange), über Änderungen benachrichtigt zu werden, aber sie wird für jede Änderung zweimal aufgerufen. Ich weiß nicht, ob das ein Fehler ist oder nicht. Wie auch immer, das Hinzufügen einer (change)Ereignisbindung scheint das Problem zu lösen.
Mark Rajcok
Außerdem habe ich den Plunker aktualisiert, der zeigt, dass er selectedItembei onChange()Bränden nicht aktualisiert wird. Daher benötigen wir anscheinend diese lokale Vorlagenvariable.
Mark Rajcok
@lux das #oder #itemin unserem Fall ist eine lokale Referenz. Deshalb können wir das item.changedort tun .
Mark Pieszak - Trilon.io
@lux, ich habe bereits beschrieben, wie man sich einbindet: an das ngModelChangebenutzerdefinierte Ereignis binden . Das Problem ist, dass <select>dieses Ereignis bei jeder Änderung zweimal ausgelöst wird.
Mark Rajcok
12

Ich bin über diese Frage gestolpert und werde meine Antwort einreichen, die ich verwendet habe und die ziemlich gut funktioniert hat. Ich hatte ein Suchfeld, das gefiltert und eine Reihe von Objekten und in meinem Suchfeld habe ich das verwendet(ngModelChange)="onChange($event)"

in meinem .html

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

dann in meinem component.ts

reSearch(newValue: string) {
    //this.searchText would equal the new value
    //handle my filtering with the new value
}
Logan H.
quelle
5
Nur zu Ihrer Information, wenn Sie an binden ngModelChange, $eventist dies kein DOM- Ereignis . Es ist vielmehr der aktuelle Wert des Formularelements, bei dem es sich um eine Zeichenfolge für ein Eingabeelement handelt.
Mark Rajcok
@ MarkRajcok Kannst du mich bitte auf die Dokumentation dazu verweisen, damit ich sie mit dem Rest meines Entwicklerteams teilen kann?
Neil S
1
@NeilS, der nächste ist angle.io/docs/ts/latest/guide/template-syntax.html#!#ngModel
Mark Rajcok