Deteksi perubahan ke ngModel pada tag pilih (Angular 2)

97

Saya mencoba untuk mendeteksi perubahan pada ngModeldalam <select>tag. Di Angular 1.x, kita mungkin menyelesaikan ini dengan $watchon ngModel, atau dengan menggunakan ngChange, tapi saya belum memahami cara mendeteksi perubahan ngModeldi Angular 2.

Contoh Lengkap : 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);
  }

}

Seperti yang bisa kita lihat, jika kita memilih nilai yang berbeda dari tarik-turun, ngModelperubahan kita , dan ekspresi yang diinterpolasi dalam tampilan mencerminkan hal ini.

Bagaimana cara mendapatkan pemberitahuan tentang perubahan ini di kelas / pengontrol saya?

lux
sumber
1
Anda mungkin ingin memeriksa beberapa komentar tambahan; Anda tidak ingin pertanyaan ini ditandai sebagai kata-kata kasar yang menyamar. stackoverflow.com/help/dont-ask .
Claies

Jawaban:

235

Pembaruan :

Pisahkan acara dan pengikatan properti:

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

Anda juga bisa menggunakan

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

dan kemudian Anda tidak perlu memperbarui model di event handler, tapi saya yakin ini menyebabkan dua peristiwa diaktifkan, jadi mungkin kurang efisien.


Jawaban lama, sebelum mereka memperbaiki bug di beta.1:

Buat variabel template lokal dan lampirkan (change)acara:

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

plunker

Lihat juga Bagaimana saya bisa mendapatkan pilihan baru di "pilih" di Angular 2?

Mark Rajcok
sumber
1
Jadi apa gunanya ngModeljika saya hanya mengikat variabel baru yang disebut item? Bukankah intinya membungkus ngModeldalam tanda kurung untuk mendapatkan event listener, jadi mengapa kita memperkenalkan variabel baru?
lux
2
@lux, ya pertanyaan yang bagus. selectedItemadalah data terikat kami, yang diperbarui secara otomatis oleh NgModel untuk kami, tetapi ... itu tidak memberi tahu kami tentang perubahan, yang seringkali cukup baik (tampilan dan semacamnya akan diperbarui), tetapi jelas ini tidak cukup baik untuk kasus penggunaan Anda. Dalam pertanyaan SO lain yang saya rujuk, saya menjelaskan bagaimana saya mencoba menggunakan (ngModelChange)untuk mendapatkan pemberitahuan perubahan, tetapi dipanggil dua kali untuk setiap perubahan. Saya tidak tahu apakah itu bug atau bukan. Bagaimanapun, menambahkan (change)pengikatan acara tampaknya menyelesaikan masalah.
Mark Rajcok
Juga, saya memperbarui plunker yang menunjukkan bahwa selectedItemtidak diperbarui saat onChange()diaktifkan, oleh karena itu tampaknya kita membutuhkan variabel template lokal itu.
Mark Rajcok
@lux the #atau #itemdalam kasus kami adalah referensi lokal . Karenanya mengapa kami bisa melakukannya di item.changesana.
Mark Pieszak - Trilon.io
@lux, saya sudah menjelaskan cara untuk menghubungkan: mengikat ke ngModelChangeacara khusus. Masalahnya, dengan <select>, peristiwa ini terpicu dua kali untuk setiap perubahan.
Mark Rajcok
12

Saya telah menemukan pertanyaan ini dan saya akan mengirimkan jawaban saya yang saya gunakan dan bekerja dengan cukup baik. Saya memiliki kotak pencarian yang memfilter dan berbagai objek dan pada kotak pencarian saya, saya menggunakan(ngModelChange)="onChange($event)"

di saya .html

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

lalu di saya component.ts

reSearch(newValue: string) {
    //this.searchText would equal the new value
    //handle my filtering with the new value
}
Logan H
sumber
5
FYI saja, saat mengikat ke ngModelChange, $eventbukanlah Peristiwa DOM . Melainkan nilai saat ini dari elemen formulir, yang merupakan string untuk elemen masukan.
Mark Rajcok
@MarkRajcok dapatkah Anda menunjukkan dokumentasi untuk ini, jadi saya dapat berbagi dengan tim pengembang saya yang lain?
Neil S
1
@NeilS, yang terdekat adalah angular.io/docs/ts/latest/guide/template-syntax.html#!#ngModel
Mark Rajcok