Evento de mudança angular 2 em cada pressionamento de tecla

282

O evento de mudança é chamado somente depois que o foco da entrada foi alterado. Como posso fazer com que o evento seja acionado a cada pressionamento de tecla?

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

A segunda ligação é alterada a cada pressionamento de tecla.

daniel
fonte

Respostas:

472

Acabei de usar a entrada do evento e funcionou bem da seguinte maneira:

no arquivo .html:

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

no arquivo .ts:

onSearchChange(searchValue: string): void {  
  console.log(searchValue);
}
Ramy Feteha
fonte
Um bom. Funciona para mim.
Godekere 19/10/19
isto é exatamente o que eu estava procurando #
Francesco Borzi
como atrasamos por algum tempo?
Mahmoud Hboubati 10/11
Funciona bem! Obrigado
Vedha Peri
Funciona muito bem, muito obrigado
Rahul Lad
193

Use ngModelChangedividindo a [(x)]sintaxe em suas duas partes, ou seja, ligação de dados de propriedades e ligação de eventos:

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

Também funciona para a tecla backspace.

Mark Rajcok
fonte
5
Porém, ao usar a banana em uma sintaxe de caixa, ela altera apenas o modelo, mas você não pode conectar algo no evento de alteração.
Giora Guttsait
4
Essa é uma ótima resposta para a melhor ligação de dados bidirecional. Deve ser a resposta aceita!
Tk1993
4
tecla de retrocesso não está atualizando o modelo
Karan Garg
4
Essa solução está correta. No entanto, esteja ciente de que o ngModelChange é acionado ANTES das atualizações de valor. Portanto, o 'newValue' neste exemplo contém o modelo SEM a tecla que você acabou de pressionar - para que você não tenha o modelo atualizado lá. Se você deseja ter o valor mais recente do modelo, use o evento (keyup).
dave0688
1
@SateeshKumarAlli qual versão do Angular você possui? Para mim ele faz detectar backspace em Angular 6.1.3
Jette
96

O evento (keyup) é sua melhor aposta.

Vamos ver o porquê:

  1. (alterar), como você mencionou, é acionado apenas quando a entrada perde o foco, portanto, é de uso limitado.
  2. (pressionamento de tecla) é acionado ao pressionar as teclas, mas não é acionado em determinadas teclas, como no backspace.
  3. (keydown) é acionado toda vez que uma tecla é pressionada. Portanto, sempre fica 1 caractere; pois obtém o estado do elemento antes do registro da tecla.
  4. (keyup) é sua melhor aposta, pois é acionada toda vez que um evento de pressionamento de tecla é concluído, portanto, isso inclui também o caractere mais recente.

Então (keyup) é o mais seguro, porque ele ...

  • registra um evento em cada pressionamento de tecla, ao contrário do evento (alteração)
  • inclui as teclas que (pressionamento de tecla) ignora
  • não tem atraso ao contrário do evento (keydown)
Sagar
fonte
4
Conforme mencionado em uma das respostas, o evento de entrada funciona muito bem. keyupé com certeza uma das opções mais seguras, no entanto, o inputevento está um passo à frente keyup. keyupao contrário input, não funciona se o valor da caixa de texto for alterado de qualquer outra maneira, por exemplo, vinculação.
211318 planet_hunter
1
Sagar, muito obrigado. Essa deve ser a resposta aceita , pois é a única a realmente abordar (change)ao lado de uma solução alternativa e depois de algumas. A resposta aceita é péssima!
Cody
Existe algum motivo específico para você querer fazer isso de novo (ngModelChange)?
SnailCoil
1
Essa deve ser a resposta aceita e mais segura, pois é nativa e oferece controle total e é muito expressiva, porque todo mundo que lê sabe exatamente quando o evento é acionado.
Florian Leitgeb
1
@ThariqNugrohotomo Não, não seria. Use (input) se você estiver procurando por algo assim.
Sagar
39
<input type="text" [ngModel]="mymodel" (keypress)="mymodel=$event.target.value"/>
{{mymodel}}
Günter Zöchbauer
fonte
10
funciona, mas estranhamente a tecla backspace não é reconhecida como pressionamento de tecla?
Daniel
22
Você pode usar keydownou keyupnão. Algumas teclas simplesmente não são acionadas keypress. Veja também stackoverflow.com/questions/4843472/…
Günter Zöchbauer
Eu tentei keydown, keyup e change events, mas quando a entrada é w, o manipulador de eventos me informa a string vazia; quando a entrada é nós, o manipulador de eventos me informa como a entrada. Você pode explicar por que esse comportamento?
premeditação 05/01
Use a tecla pressionada. A entrada ainda não foi alterada no pressionamento de tecla.
Günter Zöchbauer
1
É estranho, mas estou recebendo um atraso de entrada nisso, onde o valor não contém o valor digitado até o próximo pressionamento de tecla.
precisa
25

Uma maneira diferente de lidar com esses casos é usar o formControl e se inscrever valueChangesquando o componente for inicializado, o que permitirá que você use operadores rxjs para requisitos avançados, como a solicitação de http, aplique um debounce até que o usuário termine de escrever uma frase, use o último valor e 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
fonte
2
Isto é perfeito. Isso mantém o ruído de conversação baixo ao usá-lo para solicitações http assíncronas. Também já configura os ouvintes de eventos de mudança. Brilhante! Obrigado!
hewstone
Ainda bem que ajudou. Obrigado @hewstone
Salem Ouerdani
1
No caso de vários controlos, mesmo código pode ser aplicado comFormGroup
Vikash Kumar
20

O evento secreto que mantém ngModel angular sincronizado é a entrada da chamada de evento . Portanto, a melhor resposta para sua pergunta deve ser:

<input type="text" [(ngModel)]="mymodel" (input)="valuechange($event)" />
{{mymodel}}
Emeka Obianom
fonte
Ele faz para mim @AndreiDiaconescu
KhoPhi
O evento (entrada) não é suportado nos navegadores Edge e IE. Qual é a alternativa para isso no navegador Edge?
Sudhakar
6
<input type="text" (keypress)="myMethod(myInput.value)" #myInput />

arquivo .ts

myMethod(value:string){
...
...
}
Ulric Merguiço
fonte
Bem-vindo ao SO Ulric, explique como o seu código resolve o problema.
precisa saber é o seguinte
4

O que você está procurando é

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

Em seguida, faça o que quiser com os dados acessando o limite this.mymodelno seu arquivo .ts.

Sanket Berde
fonte
2

No meu caso, a solução é:

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

Para formulários reativos, você pode assinar as alterações feitas em todos os campos ou apenas em um campo específico.

Obtenha todas as alterações de um FormGroup:

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

Obtenha a alteração de um campo específico:

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

Eu tenho usado keyup em um campo numérico, mas hoje notei no chrome que a entrada possui botões para cima / para baixo para aumentar / diminuir o valor que não é reconhecido pelo keyup.

Minha solução é usar o keyup e alterar juntos:

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

Os testes iniciais indicam que isso funciona bem; serão postados de volta se houver algum erro encontrado após testes adicionais.

user9273992
fonte