Evento de cambio angular 2 en cada pulsación de tecla

282

El evento de cambio solo se llama después de que el foco de la entrada ha cambiado. ¿Cómo puedo hacer que el evento se active en cada pulsación de tecla?

<input type="text" [(ngModel)]="mymodel" (change)="valuechange($event)" />
{{mymodel}}

El segundo enlace cambia en cada pulsación de tecla por cierto.

daniel
fuente

Respuestas:

475

Acabo de usar la entrada del evento y funcionó bien de la siguiente manera:

en archivo .html:

<input type="text" class="form-control" (input)="onSearchChange($event.target.value)">

en el archivo .ts:

onSearchChange(searchValue: string): void {  
  console.log(searchValue);
}
Ramy Feteha
fuente
Bueno Funciona para mi.
Godekere
esto es exactamente lo que estaba buscando
Francesco Borzi
¿Cómo nos demoramos por algún tiempo?
Mahmoud Hboubati
¡Funciona genial! Gracias
Vedha Peri
Funciona muy bien, muchas gracias
Rahul Lad
193

Use ngModelChangedividiendo la [(x)]sintaxis en sus dos partes, es decir, enlace de datos de propiedad y enlace de evento:

<input type="text" [ngModel]="mymodel" (ngModelChange)="valuechange($event)" />
{{mymodel}}
valuechange(newValue) {
  mymodel = newValue;
  console.log(newValue)
}

También funciona para la tecla de retroceso.

Mark Rajcok
fuente
55
Pero cuando se usa la sintaxis de banana en una caja, solo cambia el modelo, pero no se puede enganchar algo en el evento de cambio.
Giora Guttsait
44
Esa es una gran respuesta para el mejor enlace de datos bidireccional. ¡Debería ser la respuesta aceptada!
Tk1993
44
la tecla de retroceso no actualiza el modelo
Karan Garg
44
Esa solución es correcta. Sin embargo, tenga en cuenta que ngModelChange se activa ANTES de que se actualice el valor. Entonces, 'newValue' en este ejemplo contiene el modelo SIN la tecla que acaba de presionar, por lo que no tiene el modelo actualizado allí. Si desea tener el valor del modelo más reciente, use el evento (keyup).
dave0688
1
@SateeshKumarAlli, ¿qué versión de Angular tienes? Para mí, detecta el retroceso en Angular 6.1.3
Jette
96

El evento (keyup) es tu mejor apuesta.

Veamos por qué:

  1. (cambio) como mencionó, los desencadenantes solo cuando la entrada pierde el foco, por lo tanto, es de uso limitado.
  2. (pulsación de tecla) se activa al presionar teclas, pero no se activa al presionar ciertas teclas como el retroceso.
  3. (keydown) se activa cada vez que se presiona una tecla. Por lo tanto, siempre va por 1 carácter; ya que obtiene el estado del elemento antes de que se registrara la pulsación de tecla.
  4. (keyup) es su mejor opción, ya que se activa cada vez que se completa un evento de pulsación de tecla, por lo tanto, esto también incluye el personaje más reciente.

Entonces (keyup) es el más seguro, ya que ...

  • registra un evento en cada pulsación de tecla a diferencia del evento (cambio)
  • incluye las teclas que (presionar tecla) ignora
  • no tiene retraso a diferencia del evento (keydown)
Sagar
fuente
44
Como se menciona en una de las respuestas, el evento de entrada funciona muy bien. keyupes sin duda una de las opciones más seguras, sin embargo, el inputevento está un paso por delante keyup. keyupa diferencia input, no funciona si el valor del cuadro de texto se cambia de otra manera, por ejemplo, el enlace.
planet_hunter
1
Sagar, muchas gracias. Esta debería ser la respuesta aceptada, ya que es la única que se aborda (change)junto con una solución alternativa y algo más. ¡La respuesta aceptada apesta totalmente!
Cody
¿Hay alguna razón en particular por la que quieras hacer esto (ngModelChange)?
SnailCoil
1
Esta debería ser la respuesta aceptada y más segura, ya que es nativa y le brinda control total y es muy expresiva, porque todos los que la leen saben exactamente cuándo se dispara el evento.
Florian Leitgeb
1
@ThariqNugrohotomo No, no lo haría. Use (entrada) si está buscando algo así.
Sagar
39
<input type="text" [ngModel]="mymodel" (keypress)="mymodel=$event.target.value"/>
{{mymodel}}
Günter Zöchbauer
fuente
10
funciona, pero extrañamente la tecla de retroceso no se reconoce como una pulsación de tecla?
daniel
22
Es posible que desee utilizar keydowno en su keyuplugar. Algunas teclas simplemente no se activan keypress. Ver también stackoverflow.com/questions/4843472/…
Günter Zöchbauer
He intentado eventos keydown, keyup y change, pero cuando la entrada es w, el controlador de eventos me informa una cadena vacía; cuando la entrada es nosotros, el controlador de eventos me informa w como la entrada. ¿Puede explicar por qué este comportamiento?
previsión
Use la tecla presionada. La entrada no ha cambiado aún en keydown.
Günter Zöchbauer
1
Es extraño, pero obtengo un retraso de entrada en esto donde el valor no contiene el valor escrito hasta la próxima pulsación de tecla.
Matt Eland el
25

Una forma diferente de manejar tales casos es usar formControl y suscribirse valueChangescuando se inicialice su componente, lo que le permitirá usar operadores rxjs para requisitos avanzados como realizar solicitudes http, aplicar un rebote hasta que el usuario termine de escribir una oración, tome el último valor y omitir anterior, ...

import {Component, OnInit} from '@angular/core';
import { FormControl } from '@angular/forms';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';

@Component({
  selector: 'some-selector',
  template: `
    <input type="text" [formControl]="searchControl" placeholder="search">
  `
})
export class SomeComponent implements OnInit {
  private searchControl: FormControl;
  private debounce: number = 400;

  ngOnInit() {
    this.searchControl = new FormControl('');
    this.searchControl.valueChanges
      .pipe(debounceTime(this.debounce), distinctUntilChanged())
      .subscribe(query => {
        console.log(query);
      });
  }
}
Salem Ouerdani
fuente
2
Esto es perfecto. Esto mantiene el ruido parlanchín cuando se usa para solicitudes http asíncronas. También ya configura los oyentes de eventos de cambio. ¡Brillante! ¡Gracias!
hewstone
Me alegra que haya ayudado. Gracias @hewstone
Salem Ouerdani
1
En caso de controles múltiples, se puede aplicar el mismo código conFormGroup
Vikash Kumar
20

El evento secreto que mantiene ngModel angular síncrono es la entrada de llamada de evento . Por lo tanto, la mejor respuesta a su pregunta debería ser:

<input type="text" [(ngModel)]="mymodel" (input)="valuechange($event)" />
{{mymodel}}
Emeka Obianom
fuente
Lo hace para mí @AndreiDiaconescu
KhoPhi
El evento (entrada) no es compatible con los navegadores Edge e IE. ¿Cuál es la alternativa para esto en el navegador Edge?
Sudhakar
6
<input type="text" (keypress)="myMethod(myInput.value)" #myInput />

archivo .ts

myMethod(value:string){
...
...
}
Ulric Merguiço
fuente
Bienvenido a SO Ulric, explique cómo su código resuelve el problema.
CPHPython
4

Lo que estás buscando es

<input type="text" [(ngModel)]="mymodel" (keyup)="valuechange()" />
{{mymodel}}

Luego haga lo que quiera con los datos accediendo al enlace this.mymodelen su archivo .ts.

Sanket Berde
fuente
2

En mi caso, la solución es:

[ngModel]="X?.Y" (ngModelChange)="X.Y=$event"
hatem htira
fuente
1

Para los formularios reactivos, puede suscribirse a los cambios realizados en todos los campos o solo en un campo en particular.

Obtenga todos los cambios de un FormGroup:

this.orderForm.valueChanges.subscribe(value => {
    console.dir(value);
});

Obtenga el cambio de un campo específico:

this.orderForm.get('orderPriority').valueChanges.subscribe(value => {
    console.log(value);
  });
guay
fuente
0

He estado usando keyup en un campo numérico, pero hoy noté en Chrome que la entrada tiene botones arriba / abajo para aumentar / disminuir el valor que no se reconoce por keyup.

Mi solución es usar keyup y cambiar juntos:

(keyup)="unitsChanged[i] = true" (change)="unitsChanged[i] = true"

Las pruebas iniciales indican que esto funciona bien, se volverá a publicar si se encontraron errores después de más pruebas.

usuario9273992
fuente