No AngularJS, posso rebater um modelo usando as opções do modelo ng.
ng-model-options="{ debounce: 1000 }"
Como posso rebater um modelo em Angular? Eu tentei procurar por rejeição nos documentos, mas não consegui encontrar nada.
https://angular.io/search/#stq=debounce&stp=1
Uma solução seria escrever minha própria função de debounce, por exemplo:
import {Component, Template, bootstrap} from 'angular2/angular2';
// Annotation section
@Component({
selector: 'my-app'
})
@Template({
url: 'app.html'
})
// Component controller
class MyAppComponent {
constructor() {
this.firstName = 'Name';
}
changed($event, el){
console.log("changes", this.name, el.value);
this.name = el.value;
}
firstNameChanged($event, first){
if (this.timeoutId) window.clearTimeout(this.timeoutID);
this.timeoutID = window.setTimeout(() => {
this.firstName = first.value;
}, 250)
}
}
bootstrap(MyAppComponent);
E meu html
<input type=text [value]="firstName" #first (keyup)="firstNameChanged($event, first)">
Mas estou procurando uma função de construção, existe uma no Angular?
javascript
angular
koningdavid
fonte
fonte
Respostas:
Atualizado para RC.5
Com o Angular 2, podemos rebater usando o operador RxJS
debounceTime()
em um controle de formuláriovalueChanges
observável:Plunker
O código acima também inclui um exemplo de como acelerar eventos de redimensionamento de janelas, conforme solicitado por @albanx em um comentário abaixo.
Embora o código acima seja provavelmente a maneira angular de fazê-lo, ele não é eficiente. Cada pressionamento de tecla e cada evento de redimensionamento, mesmo que sejam debitados e regulados, resultam na execução da detecção de alterações. Em outras palavras, a rejeição e a limitação não afetam a frequência com que a detecção de alterações é executada . (Encontrei um comentário do Tobias Bosch no GitHub que confirma isso.) Você pode ver isso ao executar o desentupidor e quantas vezes
ngDoCheck()
está sendo chamado quando você digita na caixa de entrada ou redimensiona a janela. (Use o botão azul "x" para executar o plunker em uma janela separada para ver os eventos de redimensionamento.)Uma técnica mais eficiente é criar o RxJS Observables a partir dos eventos, fora da "zona" do Angular. Dessa forma, a detecção de alterações não é chamada sempre que um evento é disparado. Em seus métodos de retorno de chamada de inscrição, acione manualmente a detecção de alterações - ou seja, você controla quando a detecção de alterações é chamada:
Plunker
Eu uso em
ngAfterViewInit()
vez dengOnInit()
garantir queinputElRef
está definido.detectChanges()
executará a detecção de alterações neste componente e em seus filhos. Se você preferir executar a detecção de alterações no componente raiz (por exemplo, execute uma verificação completa da detecção de alterações), use-oApplicationRef.tick()
. (ChamoApplicationRef.tick()
nos comentários no desentupidor.) Observe que chamartick()
fará comngDoCheck()
que seja chamado.fonte
.fromEvent()
assinaturasSe você não deseja lidar
@angular/forms
, basta usar um RxJSSubject
com ligações de alteração.view.component.html
view.component.ts
Isso dispara a detecção de alterações. Para uma maneira que não aciona a detecção de alterações, confira a resposta de Mark.
Atualizar
.pipe(debounceTime(300), distinctUntilChanged())
é necessário para o rxjs 6.Exemplo:
fonte
.pipe(debounceTime(300), distinctUntilChanged())
é necessário para o rxjs 6keyUp
evento oninput.nativeElement
em amat-table
, que parou de funcionar quando o número de colunas foi alteradoPoderia ser implementado como diretiva
use-o como
amostra de componente
fonte
import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/distinctUntilChanged';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
this.model.valueChanges .debounceTime(this.debounceTime) .distinctUntilChanged()
this.model.valueChanges .pipe( debounceTime(this.debounceTime), distinctUntilChanged() )
Como o tópico é antigo, a maioria das respostas não funciona no Angular 6/7/8/9 e / ou usa outras bibliotecas.
Então, aqui está uma solução curta e simples para Angular 6+ com RxJS.
Importe o material necessário primeiro:
Inicialize em
ngOnInit
:Use desta maneira:
PS: Para soluções mais complexas e eficientes, convém verificar outras respostas.
fonte
Não é acessível diretamente como no angular1, mas você pode jogar facilmente com os observáveis NgFormControl e RxJS:
Esta postagem do blog explica claramente: http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html
Aqui é para um preenchimento automático, mas funciona em todos os cenários.
fonte
[...]
é uma ligação de destino unidirecional. Por que o contêiner pode ser notificadovalueChanges
? não deveria ter que ser sth. gosta(ngFormControl)="..."
?Você pode criar um RxJS (v.6) Observable que faz o que quiser.
view.component.html
view.component.ts
fonte
rsjs/Rx
, eu tinha erros ao utilizar a importação do jeito que você escreveu ... Então, no meu caso, é agora:import { Observable } from 'rxjs/Rx';
import { Observable } from 'rxjs';
.pipe
chamadapipe(debounceTime(300), distinctUntilChanged())
Para quem usa o lodash, é extremamente fácil renunciar a qualquer função:
então apenas jogue algo assim no seu modelo:
fonte
Solução com assinante de inicialização diretamente na função de evento:
E html:
fonte
Resolvi isso escrevendo um decorador de debounce. O problema descrito pode ser resolvido aplicando o @debounceAccessor ao acessador definido da propriedade.
Também forneci um decorador de debounce adicional para métodos, que podem ser úteis para outras ocasiões.
Isso facilita muito a rejeição de uma propriedade ou método. O parâmetro é o número de milissegundos que o debounce deve durar, 100 ms no exemplo abaixo.
E aqui está o código para os decoradores:
Eu adicionei um parâmetro adicional para o decorador do método, que permite acionar o método APÓS o atraso do rebounce. Fiz isso para que, por exemplo, pudesse ser usado quando associado a eventos de mouseover ou redimensionamento, onde eu queria que a captura ocorresse no final do fluxo de eventos. Nesse caso, no entanto, o método não retornará um valor.
fonte
Podemos criar uma diretiva [debounce] que sobrescreve a função viewToModelUpdate padrão do ngModel por uma vazia.
Código da Diretiva
Como usá-lo
fonte
Arquivo HTML:
Arquivo TS:
fonte
A solução simples seria criar uma diretiva que você possa aplicar a qualquer controle.
uso seria
fonte
Angular 7
.Passei horas nisso, espero que eu possa economizar alguém mais algum tempo. Para mim, a seguinte abordagem para usar
debounce
em um controle é mais intuitiva e fácil de entender para mim. Ele foi desenvolvido com base na solução angular.io docs para preenchimento automático, mas com a capacidade de interceptar as chamadas sem precisar depender de vincular os dados ao DOM.Plunker
Um cenário de caso de uso para isso pode estar verificando um nome de usuário após a digitação para ver se alguém já o usou e avisando o usuário.
Nota: não esqueça,
(blur)="function(something.value)
pode fazer mais sentido para você, dependendo de suas necessidades.fonte
DebounceTime no Angular 7 com RxJS v6
Link de origem
Link de demonstração
No modelo HTML
No componente
fonte
Você também pode resolver isso usando decoradores. Para uma instância, usando o decorador debounce de utils-decorator lib (
npm install utils-decorators
):fonte
Esta é a melhor solução que encontrei até agora. Atualiza o
ngModel
emblur
edebounce
conforme emprestado de https://stackoverflow.com/a/47823960/3955513
Depois, em HTML:
No
blur
modelo é explicitamente atualizado usando javascript simples.Exemplo aqui: https://stackblitz.com/edit/ng2-debounce-working
fonte