Événement de changement angulaire 2 à chaque pression de touche


282

L'événement change n'est appelé qu'après que le focus de l'entrée a changé. Comment puis-je faire en sorte que l'événement se déclenche à chaque pression de touche?

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

La deuxième liaison change à chaque pression de touche btw.

Réponses:


475

Je viens d'utiliser l'entrée d'événement et cela a bien fonctionné comme suit:

dans le fichier .html:

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

dans le fichier .ts:

onSearchChange(searchValue: string): void {  
  console.log(searchValue);
}

Bon. Travaille pour moi.
Godekere

c'est exactement ce que je cherchais
Francesco Borzi

comment retardons-nous un certain temps?
Mahmoud Hboubati

Fonctionne très bien! Merci
Vedha Peri

Fonctionne très bien, merci beaucoup
Rahul Lad

193

À utiliser ngModelChangeen décomposant la [(x)]syntaxe en ses deux parties, à savoir la liaison de données de propriété et la liaison d'événement:

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

Cela fonctionne également pour la touche de retour arrière.


5
Mais lorsque vous utilisez la banane dans une syntaxe de boîte, cela ne change que le modèle, mais vous ne pouvez pas accrocher quelque chose à l'événement de changement.
Giora Guttsait

4
C'est une excellente réponse pour la meilleure liaison de données bidirectionnelle. Devrait être la réponse acceptée!
Tk1993

4
la touche de retour arrière ne met pas à jour le modèle
Karan Garg

4
Cette solution est correcte. Cependant, sachez que ngModelChange est déclenché AVANT la mise à jour des valeurs. Ainsi, la «nouvelleValeur» dans cet exemple contient le modèle SANS la touche que vous venez d'appuyer - vous n'avez donc pas le modèle mis à jour là-bas. Si vous souhaitez avoir la valeur de modèle la plus récente, utilisez l'événement (keyup).
dave0688

1
@SateeshKumarAlli quelle version d'Angular avez-vous? Pour moi, il détecte le retour arrière dans Angular 6.1.3
Jette

96

L'événement (keyup) est votre meilleur pari.

Voyons pourquoi:

  1. (changement) comme vous l'avez mentionné ne se déclenche que lorsque l'entrée perd le focus, donc est d'une utilité limitée.
  2. (pression de touche) se déclenche à la pression des touches mais ne se déclenche pas sur certaines frappes comme le retour arrière.
  3. (keydown) se déclenche chaque fois qu'une touche est enfoncée. D'où toujours un retard de 1 caractère; car il obtient l'état de l'élément avant l'enregistrement de la frappe.
  4. (keyup) est votre meilleur pari car il se déclenche à chaque fois qu'un événement push clé est terminé, donc cela inclut également le personnage le plus récent.

Donc (keyup) est le plus sûr car il ...

  • enregistre un événement à chaque frappe, contrairement à l'événement (change)
  • inclut les touches que (pression sur une touche) ignore
  • n'a pas de décalage contrairement à l'événement (keydown)

4
Comme mentionné dans l'une des réponses, l'événement d'entrée fonctionne très bien. keyupest à coup sûr l'une des options les plus sûres, mais l' inputévénement a une longueur d'avance keyup. keyupcontrairement à input, ne fonctionne pas si la valeur de la zone de texte est modifiée d'une autre manière, par exemple la liaison.
planet_hunter

1
Sagar, merci beaucoup. Cela devrait être la réponse acceptée car c'est la seule à aborder en (change)même temps qu'une solution de contournement, puis certaines. La réponse acceptée craint totalement!
Cody

y a-t-il une raison particulière pour laquelle vous voudriez recommencer (ngModelChange)?
SnailCoil

1
Cela devrait être la réponse acceptée et la plus sûre car elle est native et vous donne un contrôle total et elle est très expressive, car tous ceux qui la lisent savent exactement quand l'événement est déclenché.
Florian Leitgeb

1
@ThariqNugrohotomo Non, ce ne serait pas le cas. Utilisez (entrée) si vous cherchez quelque chose comme ça.
Sagar

39
<input type="text" [ngModel]="mymodel" (keypress)="mymodel=$event.target.value"/>
{{mymodel}}

10
fonctionne, mais étrangement la touche de retour arrière n'est pas reconnue comme une pression de touche?
daniel

22
Vous voudrez peut-être utiliser keydownou à la keyupplace. Certaines touches ne fonctionnent tout simplement pas keypress. Voir aussi stackoverflow.com/questions/4843472/…
Günter Zöchbauer

J'ai essayé les événements keydown, keyup et change mais quand l'entrée est w le gestionnaire d'événements me rapporte une chaîne vide; lorsque l'entrée est nous le gestionnaire d'événements me rapporte w comme entrée. Pouvez-vous expliquer pourquoi ce comportement?
prévoyance

Appuyez sur la touche. L'entrée n'a pas encore changé lors du keydown.
Günter Zöchbauer

1
C'est étrange, mais j'obtiens un décalage d'entrée sur ce point où la valeur ne contient pas la valeur saisie jusqu'à la prochaine pression de touche.
Matt Eland

25

Une autre façon de gérer de tels cas est d'utiliser formControl et de vous y abonner valueChangeslorsque votre composant est initialisé, ce qui vous permettra d'utiliser les opérateurs rxjs pour des exigences avancées telles que l'exécution de requêtes http, d'appliquer un rebounce jusqu'à ce que l'utilisateur ait fini d'écrire une phrase, de prendre la dernière valeur et omettre le précédent, ...

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);
      });
  }
}

2
C'est parfait. Cela réduit le bruit de discussion lorsque vous l'utilisez pour les requêtes http asynchrones. Configure également déjà les écouteurs d'événement de changement. Brillant! Merci!
hewstone

Heureux que cela ait aidé. Merci @hewstone
Salem Ouerdani

1
En cas de contrôles multiples, le même code peut être appliqué avecFormGroup
Vikash Kumar

20

L'événement secret qui maintient le ngModel angulaire synchrone est l' entrée d' appel d'événement . Par conséquent, la meilleure réponse à votre question devrait être:

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

Cela fait pour moi @AndreiDiaconescu
KhoPhi

L'événement (entrée) n'est pas pris en charge dans les navigateurs Edge et IE. Quelle est l'alternative pour cela dans le navigateur Edge?
Sudhakar du

6
<input type="text" (keypress)="myMethod(myInput.value)" #myInput />

archive .ts

myMethod(value:string){
...
...
}

Bienvenue à SO Ulric, veuillez expliquer comment votre code résout le problème.
CPHPython

4

Ce que vous cherchez c'est

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

this.mymodelFaites ensuite ce que vous voulez avec les données en accédant à la limite de votre fichier .ts.


2

Dans mon cas, la solution est:

[ngModel]="X?.Y" (ngModelChange)="X.Y=$event"

1

Pour les formulaires réactifs, vous pouvez vous abonner aux modifications apportées à tous les champs ou simplement à un champ particulier.

Obtenez toutes les modifications d'un FormGroup:

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

Obtenez le changement d'un champ spécifique:

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

0

J'utilise keyup sur un champ numérique, mais aujourd'hui j'ai remarqué en chrome l'entrée a des boutons haut / bas pour augmenter / diminuer la valeur qui n'est pas reconnue par keyup.

Ma solution consiste à utiliser les touches et à changer ensemble:

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

Les tests initiaux indiquent que cela fonctionne bien, publieront si des bogues ont été trouvés après des tests supplémentaires.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.