En AngularJS puedo eliminar el rebote de un modelo usando las opciones ng-model.
ng-model-options="{ debounce: 1000 }"
¿Cómo puedo eliminar el rebote de un modelo en Angular? Traté de buscar el rebote en los documentos pero no pude encontrar nada.
https://angular.io/search/#stq=debounce&stp=1
Una solución sería escribir mi propia función antirrebote, por ejemplo:
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);
Y mi html
<input type=text [value]="firstName" #first (keyup)="firstNameChanged($event, first)">
Pero estoy buscando una función integrada, ¿hay alguna en Angular?
javascript
angular
koningdavid
fuente
fuente
Respuestas:
Actualizado para RC.5
Con Angular 2 podemos eliminar el rebote usando el operador RxJS
debounceTime()
en unvalueChanges
observable de control de formulario :Plunker
El código anterior también incluye un ejemplo de cómo regular los eventos de cambio de tamaño de la ventana, como lo solicitó @albanx en un comentario a continuación.
Aunque el código anterior es probablemente la forma angular de hacerlo, no es eficiente. Cada pulsación de tecla y cada evento de cambio de tamaño, aunque se eliminen y se limiten, da como resultado la detección de cambios en ejecución. En otras palabras, la eliminación de rebotes y la limitación no afectan la frecuencia con la que se ejecuta la detección de cambios . (Encontré un comentario de GitHub de Tobias Bosch que confirma esto). Puedes ver esto cuando ejecutas el plunker y ves cuántas veces
ngDoCheck()
se llama cuando escribes en el cuadro de entrada o cambias el tamaño de la ventana. (Use el botón azul "x" para ejecutar el plunker en una ventana separada para ver los eventos de cambio de tamaño).Una técnica más eficiente es crear RxJS Observables usted mismo a partir de los eventos, fuera de la "zona" de Angular. De esta manera, la detección de cambios no se llama cada vez que se dispara un evento. Luego, en sus métodos de devolución de llamada de suscripción, active manualmente la detección de cambios, es decir, usted controla cuándo se llama a la detección de cambios:
Plunker
Lo uso en
ngAfterViewInit()
lugar dengOnInit()
asegurarme de queinputElRef
esté definido.detectChanges()
ejecutará la detección de cambios en este componente y sus hijos. Si prefiere ejecutar la detección de cambios desde el componente raíz (es decir, ejecutar una verificación de detección de cambios completa), utiliceApplicationRef.tick()
en su lugar. (Puse una llamadaApplicationRef.tick()
en los comentarios en el plunker). Tenga en cuenta que llamartick()
harángDoCheck()
que se llame.fuente
.fromEvent()
suscripcionesSi no desea tratar
@angular/forms
, puede usar un RxJSSubject
con enlaces de cambio.view.component.html
view.component.ts
Esto activa la detección de cambios. Para una forma que no active la detección de cambios, consulte la respuesta de Mark.
Actualizar
.pipe(debounceTime(300), distinctUntilChanged())
es necesario para rxjs 6.Ejemplo:
fuente
.pipe(debounceTime(300), distinctUntilChanged())
es necesario para rxjs 6keyUp
event oninput.nativeElement
enmat-table
, que dejó de funcionar cuando se cambió el número de columnasPodría implementarse como Directiva
úsalo como
muestra componente
fuente
import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/distinctUntilChanged';
toimport { debounceTime, distinctUntilChanged } from 'rxjs/operators';
andthis.model.valueChanges .debounceTime(this.debounceTime) .distinctUntilChanged()
tothis.model.valueChanges .pipe( debounceTime(this.debounceTime), distinctUntilChanged() )
Como el tema es antiguo, la mayoría de las respuestas no funcionan en Angular 6/7/8/9 y / o usan otras librerías.
Así que aquí hay una solución corta y simple para Angular 6+ con RxJS.
Importa las cosas necesarias primero:
Inicializar en
ngOnInit
:Use de esta manera:
PD: para soluciones más complejas y eficientes, es posible que aún desee consultar otras respuestas.
fuente
No es accesible directamente como en angular1 pero puedes jugar fácilmente con NgFormControl y observables RxJS:
Esta publicación de blog lo explica claramente: http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html
Aquí es para un autocompletado pero funciona en todos los escenarios.
fuente
[...]
es un enlace de destino unidireccional. ¿Por qué se puede notificar al contenedorvalueChanges
? ¿No debería ser algo? como(ngFormControl)="..."
?Puede crear una RxJS (v.6) observable que haga lo que quiera.
view.component.html
view.component.ts
fuente
rsjs/Rx
, tuve errores cuando se utiliza la importación de la manera que lo has escrito ... por lo que en mi caso es ahora:import { Observable } from 'rxjs/Rx';
import { Observable } from 'rxjs';
.pipe
llamadapipe(debounceTime(300), distinctUntilChanged())
Para cualquiera que use lodash, es extremadamente fácil eliminar cualquier función:
entonces simplemente arroje algo como esto en su plantilla:
fuente
Solución con suscriptor de inicialización directamente en función de evento:
Y html:
fuente
Resolví esto escribiendo un decorador antirrebote. El problema descrito podría resolverse aplicando @debounceAccessor al conjunto de acceso de la propiedad.
También he suministrado un decorador antirrebote adicional para métodos, que puede ser útil para otras ocasiones.
Esto hace que sea muy fácil eliminar el rebote de una propiedad o un método. El parámetro es el número de milisegundos que debe durar el rebote, 100 ms en el siguiente ejemplo.
Y aquí está el código para los decoradores:
Agregué un parámetro adicional para el decorador de métodos que le permite activar el método DESPUÉS del retraso de rebote. Lo hice para poder usarlo, por ejemplo, cuando se combina con mouseover o cambiar el tamaño de los eventos, donde quería que la captura ocurriera al final de la secuencia de eventos. En este caso, sin embargo, el método no devolverá un valor.
fuente
Podemos crear una directiva [debounce] que sobrescribe la función viewToModelUpdate predeterminada de ngModel con una vacía.
Código de directiva
Cómo usarlo
fuente
Archivo HTML:
Archivo TS:
fuente
Una solución simple sería crear una directiva que pueda aplicar a cualquier control.
el uso sería
fuente
Angular 7
.Pasé horas en esto, espero poder salvar a alguien más en algún momento. Para mí, el siguiente enfoque para usar
debounce
en un control es más intuitivo y más fácil de entender para mí. Se basa en la solución angular.io docs para autocompletar, pero con la capacidad de interceptar las llamadas sin tener que depender de vincular los datos al DOM.Saqueador
Un escenario de caso de uso para esto podría ser verificar un nombre de usuario después de escribirlo para ver si alguien ya lo ha tomado, y luego advertir al usuario.
Nota: no lo olvide,
(blur)="function(something.value)
podría tener más sentido para usted según sus necesidades.fuente
DebounceTime en Angular 7 con RxJS v6
Enlace fuente
Enlace de demostración
En plantilla HTML
En componente
fuente
También podría resolver esto usando un decorador, por ejemplo, usando el decorador debounce de utils-decorator lib (
npm install utils-decorators
):fuente
Esta es la mejor solución que he encontrado hasta ahora. Actualiza la
ngModel
sobreblur
ydebounce
prestado de https://stackoverflow.com/a/47823960/3955513
Luego en HTML:
En
blur
el modelo se actualiza explícitamente usando JavaScript simple.Ejemplo aquí: https://stackblitz.com/edit/ng2-debounce-working
fuente