Detectar el cambio a ngModel en una etiqueta de selección (Angular 2)

97

Estoy intentando detectar un cambio ngModelen una <select>etiqueta. En Angular 1.x, podríamos resolver esto con un $watchon ngModel, o usando ngChange, pero todavía tengo que entender cómo detectar un cambio ngModelen Angular 2.

Ejemplo completo : 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);
  }

}

Como podemos ver, si seleccionamos un valor diferente del menú desplegable, nuestros ngModelcambios y la expresión interpolada en la vista lo refleja.

¿Cómo me notifican de este cambio en mi clase / controlador?

lux
fuente
1
es posible que desee controlar algunos de los comentarios adicionales; no desea que esta pregunta se marque como una perorata disfrazada. stackoverflow.com/help/dont-ask .
Claies

Respuestas:

234

Actualización :

Separe las vinculaciones de eventos y propiedades:

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

También podrías usar

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

y luego no tendría que actualizar el modelo en el controlador de eventos, pero creo que esto hace que se activen dos eventos, por lo que probablemente sea menos eficiente.


Respuesta anterior, antes de que arreglaran un error en beta.1:

Cree una variable de plantilla local y adjunte un (change)evento:

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

plunker

Consulte también ¿Cómo puedo obtener una nueva selección en "seleccionar" en Angular 2?

Mark Rajcok
fuente
1
Entonces, ¿cuál es el punto de ngModelsi solo estoy vinculando una nueva variable llamada item? ¿No es el punto de ajustar ngModelentre paréntesis para adquirir oyentes de eventos, entonces, por qué estamos introduciendo una nueva variable?
lux
2
@lux, sí, buena pregunta. selectedItemson nuestros datos vinculados, que NgModel actualiza automáticamente por nosotros, pero ... no nos notifica los cambios, lo que a menudo es lo suficientemente bueno (las vistas y demás se actualizarán), pero obviamente esto no es lo suficientemente bueno para su caso de uso. En la otra pregunta SO a la que hice referencia, describo cómo traté de usar (ngModelChange)para recibir notificaciones de cambios, pero se llama dos veces para cada cambio. No sé si eso es un error o no. De todos modos, agregar un (change)enlace de evento parece resolver el problema.
Mark Rajcok
Además, actualicé el plunker que muestra que selectedItemno se actualiza cuando se onChange()dispara, por lo que parece que necesitamos esa variable de plantilla local.
Mark Rajcok
@lux the #o #itemen nuestro caso es una referencia local . De ahí por qué podemos hacerlo item.changeallí.
Mark Pieszak - Trilon.io
@lux, ya describí la forma de conectar: ​​enlazar al ngModelChangeevento personalizado. El problema es que <select>este evento se dispara dos veces por cada cambio.
Mark Rajcok
12

Me he encontrado con esta pregunta y enviaré mi respuesta que usé y funcioné bastante bien. Tenía un cuadro de búsqueda que filtraba una serie de objetos y en mi cuadro de búsqueda usé el(ngModelChange)="onChange($event)"

en mi .html

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

entonces en mi component.ts

reSearch(newValue: string) {
    //this.searchText would equal the new value
    //handle my filtering with the new value
}
Logan H
fuente
5
Solo para su información, cuando se vincula a ngModelChange, $eventno es un evento DOM . Más bien es el valor actual del elemento de formulario, que es una cadena para un elemento de entrada.
Mark Rajcok
@MarkRajcok, ¿puede indicarme la documentación para esto, para que pueda compartirla con el resto de mi equipo de desarrollo?
Neil S
1
@NeilS, el más cercano es angular.io/docs/ts/latest/guide/template-syntax.html#!#ngModel
Mark Rajcok