Zdarzenie zmiany Angular 2 przy każdym naciśnięciu klawisza

282

Zdarzenie zmiany jest wywoływane dopiero po zmianie fokusa wejścia. Jak mogę to zrobić, aby zdarzenie było uruchamiane przy każdym naciśnięciu klawisza?

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

Drugie wiązanie zmienia się przy każdym naciśnięciu klawisza btw.

Daniel
źródło

Odpowiedzi:

472

Właśnie użyłem danych wejściowych zdarzenia i działało to w następujący sposób:

w pliku .html:

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

w pliku .ts:

onSearchChange(searchValue: string): void {  
  console.log(searchValue);
}
Ramy Feteha
źródło
Dobry. Pracuje dla mnie.
Godekere,
tego właśnie szukałem
Francesco Borzi
jak opóźnimy się o jakiś czas?
Mahmoud Hboubati,
Działa świetnie! Dziękuję
Vedha Peri,
Działa świetnie, wielkie dzięki
Rahul Lad
193

Użyj ngModelChange, dzieląc [(x)]składnię na dwie części, tj. Wiązanie danych właściwości i wiązanie zdarzeń:

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

Działa również z klawiszem Backspace.

Mark Rajcok
źródło
5
Ale gdy używasz banana w składni pudełkowej, zmienia on tylko model, ale nie możesz zaczepić czegoś o zdarzeniu zmiany.
Giora Guttsait
4
To świetna odpowiedź na najlepsze dwukierunkowe wiązanie danych. Powinna być zaakceptowana odpowiedź!
Tk1993
4
Klawisz Backspace nie aktualizuje modelu
Karan Garg
4
To rozwiązanie jest poprawne. Należy jednak pamiętać, że ngModelChange jest uruchamiany PRZED aktualizacją wartości. Zatem „newValue” w tym przykładzie zawiera model BEZ właśnie naciśniętego klawisza - więc nie ma tam zaktualizowanego modelu. Jeśli chcesz mieć najnowszą wartość modelu, użyj zdarzenia (keyup).
dave0688
1
@SateeshKumarAlli, którą wersję Angulara posiadasz? Dla mnie wykrywa on backspace w Angular 6.1.3
Jette
96

Wydarzenie (keyup) jest najlepszym wyborem.

Zobaczmy, dlaczego:

  1. (zmień), jak wspomniałeś, wyzwalacze tylko wtedy, gdy sygnał wejściowy traci fokus, dlatego ma ograniczone zastosowanie.
  2. (naciśnięcie klawisza) uruchamia się po naciśnięciu klawisza, ale nie uruchamia się po niektórych naciśnięciach klawiszy, takich jak Backspace.
  3. (keydown) uruchamia się za każdym razem, gdy klawisz jest wciśnięty w dół. Dlatego zawsze jest opóźniony o 1 znak; ponieważ dostaje stan elementu przed zarejestrowaniem naciśnięcia klawisza.
  4. (keyup) jest twoim najlepszym zakładem, ponieważ uruchamia się za każdym razem, gdy kończy się zdarzenie push push, dlatego obejmuje to również najnowszą postać.

Tak więc (keyup) jest najbezpieczniejszy, ponieważ ...

  • rejestruje zdarzenie przy każdym naciśnięciu klawisza, w przeciwieństwie do zdarzenia (zmiany)
  • obejmuje klawisze, które (naciśnięcie klawisza) ignoruje
  • nie ma opóźnienia w przeciwieństwie do zdarzenia (keydown)
Sagar
źródło
4
Jak wspomniano w jednej z odpowiedzi, zdarzenie wejściowe działa naprawdę dobrze. keyupjest z pewnością jedną z najbezpieczniejszych opcji, jednak inputwydarzenie jest o krok do przodu keyup. keyupw przeciwieństwie do inputnie działa, jeśli wartość pola tekstowego jest zmieniana w jakikolwiek inny sposób, np. wiązanie.
planet_hunter
1
Sagar, dziękuję bardzo. Powinna to być odpowiedź zaakceptowana, ponieważ jest to jedyna odpowiedź, którą należy rozwiązać (change)obok obejścia, a następnie niektóre. Przyjęta odpowiedź jest do kitu!
Cody
czy jest jakiś konkretny powód, dla którego chciałbyś to zrobić (ngModelChange)?
SnailCoil,
1
To powinna być zaakceptowana i najbezpieczniejsza odpowiedź, ponieważ jest rodzima i daje pełną kontrolę i jest bardzo ekspresyjna, ponieważ każdy, kto ją czyta, wie dokładnie, kiedy wydarzenie zostanie uruchomione.
Florian Leitgeb
1
@ThariqNugrohotomo Nie, nie zrobiłby tego. Użyj (danych wejściowych), jeśli szukasz czegoś takiego.
Sagar,
39
<input type="text" [ngModel]="mymodel" (keypress)="mymodel=$event.target.value"/>
{{mymodel}}
Günter Zöchbauer
źródło
10
działa, ale co dziwne, klawisz Backspace nie jest rozpoznawany jako naciśnięcie klawisza?
Daniel
22
Możesz użyć keydownlub keyupzamiast tego. Niektóre klucze po prostu się nie uruchamiają keypress. Zobacz także stackoverflow.com/questions/4843472/…
Günter Zöchbauer,
Próbowałem keydown, keyup i zmiany zdarzeń, ale gdy dane wejściowe są w, moduł obsługi zdarzeń zgłasza mi pusty ciąg znaków; gdy dane wejściowe to my, moduł obsługi zdarzeń zgłasza mi jako dane wejściowe. Czy możesz wyjaśnić, dlaczego to zachowanie?
przemyślał
Użyj klawisza. Dane wejściowe nie zmieniły się jeszcze podczas keydown.
Günter Zöchbauer
1
To dziwne, ale dostaję opóźnienie na wejściu, w którym wartość nie zawiera wpisanej wartości do następnego naciśnięcia klawisza.
Matt Eland
25

Innym sposobem radzenia sobie z takimi przypadkami jest użycie formControl i zasubskrybowanie go valueChangespodczas inicjowania komponentu, co pozwoli ci używać operatorów rxjs do zaawansowanych wymagań, takich jak wykonywanie żądań HTTP, stosowanie debounce do momentu, aż użytkownik skończy pisać zdanie, przyjmie ostatnią wartość i pomiń poprzednie ...

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
źródło
2
To jest doskonałe. Dzięki temu hałas jest cichy, gdy używasz go do asynchronicznych żądań HTTP. Konfiguruje także nasłuchiwania zdarzeń zmiany. Znakomity! Dzięki!
hewstone
Cieszę się, że pomogło. Dzięki @hewstone
Salem Ouerdani,
1
W przypadku wielu kontrolek można zastosować ten sam kod za pomocąFormGroup
Vikash Kumar,
20

Sekretnym zdarzeniem, które utrzymuje synchronizację kątową ngModel, jest wejście wywołania zdarzenia . Dlatego najlepszą odpowiedzią na twoje pytanie powinno być:

<input type="text" [(ngModel)]="mymodel" (input)="valuechange($event)" />
{{mymodel}}
Emeka Obianom
źródło
To robi dla mnie @AndreiDiaconescu
KhoPhi
Zdarzenie (wejściowe) nie jest obsługiwane w przeglądarkach Edge i IE. Jaka jest alternatywa dla tego w przeglądarce Edge?
Sudhakar,
6
<input type="text" (keypress)="myMethod(myInput.value)" #myInput />

archiwum .ts

myMethod(value:string){
...
...
}
Ulric Merguiço
źródło
Witamy w SO Ulric, proszę wyjaśnić, w jaki sposób Twój kod rozwiązuje problem.
CPHPython
4

To czego szukasz

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

Następnie rób co chcesz z danymi, uzyskując dostęp do powiązania this.mymodelw pliku .ts.

Sanket Berde
źródło
2

W moim przypadku rozwiązaniem jest:

[ngModel]="X?.Y" (ngModelChange)="X.Y=$event"
hatem htira
źródło
1

W przypadku formularzy reaktywnych możesz subskrybować zmiany wprowadzone we wszystkich polach lub tylko w określonym polu.

Pobierz wszystkie zmiany z FormGroup:

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

Uzyskaj zmianę określonego pola:

this.orderForm.get('orderPriority').valueChanges.subscribe(value => {
    console.log(value);
  });
pozostawanie chłodnym
źródło
0

Używam keyup na polu liczbowym, ale dzisiaj zauważyłem w chromie, że wejście ma przyciski góra / dół do zwiększania / zmniejszania wartości, które nie są rozpoznawane przez keyup.

Moim rozwiązaniem jest użycie klucza i zmiana razem:

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

Wstępne testy wskazują, że to działa poprawnie, prześlemy je ponownie, jeśli zostaną wykryte błędy po dalszych testach.

użytkownik9273992
źródło