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

daniel
la source

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);
}
Ramy Feteha
la source
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.

Mark Rajcok
la source
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)
Sagar
la source
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}}
Günter Zöchbauer
la source
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);
      });
  }
}
Salem Ouerdani
la source
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}}
Emeka Obianom
la source
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){
...
...
}
Ulric Merguiço
la source
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.

Sanket Berde
la source
2

Dans mon cas, la solution est:

[ngModel]="X?.Y" (ngModelChange)="X.Y=$event"
hatem htira
la source
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);
  });
rester cool
la source
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.

user9273992
la source