Reputation: 4756
How can I debounce a function which gets called on an "keyUp" event?
Here is my code:
My Function
private handleSearch(searchTextValue: string, skip?: number): void {
this.searchTextValue = searchTextValue;
if (this.skip === 0 || typeof skip === "undefined") {
this.skip = 0;
this.pageIndex = 1;
} else {
this.skip = skip;
}
this.searchTextChanged.emit({ searchTextValue: searchTextValue, skip: this.skip, take: this.itemsPerPage });
}
My HTML
<input type="text" class="form-control" placeholder="{{ 'searchquery' | translate }}" id="searchText" #searchText (keyup)="handleSearch(searchText.value)">
Bassically what I'm trying to achieve is that handleSearch
gets called a few moments after the user stop typing.
I found out i can use lodash's _debounce()
for this, but I haven't found out how to put this on my keyUp
event.
Upvotes: 24
Views: 27836
Reputation: 4190
Take a look at answer here: https://stackoverflow.com/a/35992325/751200
And article here: https://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html (quite old, but still good).
Basically, you can use an Observable object provided by Angular Forms.
For example, this.myFormGroup.get("searchText").valueChanges.pipe(debounceTime(500), distinctUntilChanged()).subscribe(...)
If you need to perform an HTTP request when user stops typing, you can place such HTTP call into switchMap
operator and add it to pipe
list:
this.myFormGroup.get("searchText")
.valueChanges
.pipe(debounceTime(500),
distinctUntilChanged(),
switchMap((value: string) => {
return this.service.getData(value);
}))
.subscribe((valueFromRest) => { ... });
The magic in switchMap
will automatically cancel the previous HTTP request (if it's not completed yet) and start a new one automatically.
Upvotes: 2
Reputation: 15353
UPDATE: Using RXJS 6 pipe operator:
this.subject.pipe(
debounceTime(500)
).subscribe(searchTextValue => {
this.handleSearch(searchTextValue);
});
You could create a rxjs/Subject and call .next() on keyup and subscribe to it with your desired debounceTime.
I'm not sure if it is the right way to do it but it works.
private subject: Subject<string> = new Subject();
ngOnInit() {
this.subject.debounceTime(500).subscribe(searchTextValue => {
this.handleSearch(searchTextValue);
});
}
onKeyUp(searchTextValue: string){
this.subject.next(searchTextValue);
}
HTML:
<input (keyup)="onKeyUp(searchText.value)">
Upvotes: 55
Reputation: 728
An Update for Rx/JS 6. Using the Pipe Operator.
import { debounceTime } from 'rxjs/operators';
this.subject.pipe(
debounceTime(500)
).subscribe(searchTextValue => {
this.handleSearch(searchTextValue);
});
Everything else is the same 👍
Upvotes: 24