Reputation: 61
I'm new to Angular, and any other programming languages really... So even though there are other posts about this subject, I didn't quite understand how to apply debounceTime into my project, as the code I came up with for executing the search is different from the others.
I have an input on the html that calls a function on keyup event, like so:
<input type="text" class="layout-search theme-search" placeholder="Pesquise outro vendedor ou unidade aqui..."
(click)="searchError = false" (keyup)="search($event.target.value)" />
The function search() that lives in the component's ts file is:
searchResult: Search;
search(searchValue: any) {
if (searchValue.length >= 3) {
this.searchService.getSearch(searchValue)
.subscribe(
value => {
this.searchResult = value;
this.searchError = false;
},
error => this.searchError = true
);
} else {
this.searchResult = undefined;
}
}
and the searchService:
export class SearchService {
private apiSearch = environment.apiBaseUrl + 'search/?search=';
constructor(private http: HttpClient) { }
getSearch(value: any): Observable<Search> {
return this.http.get<Search>(this.apiSearch + value);
}
I have imported debounceTime into the component:
import { debounceTime } from 'rxjs/operators';
and tried editing search() to:
searchResult: Search;
search(searchValue: any) {
if (searchValue.length >= 3) {
this.searchService.getSearch(searchValue)
.pipe(debounceTime(1000))
.subscribe(
value => {
this.searchResult = value;
this.searchError = false;
},
error => this.searchError = true
);
} else {
this.searchResult = undefined;
}
}
But it doesnt's seem to work, nor does any errors show up on the browser or VS Code. The way it is right now, the search works fine, but for every key pressed into the input the API is requested.
Upvotes: 2
Views: 1159
Reputation: 2422
I've implemented this before, and instead of calling a function on the (keyup)
output from the input
element, I created an Observable using fromEvent
that listens to the keyup event. Here's the function:
setupTypeaheadObservable() {
fromEvent(this.searchInput.nativeElement, 'keyup')
.pipe(
map((ev: KeyboardEvent) => {
if (ev && ev.key === 'Escape') {
this.searchInput.nativeElement.blur();
}
return ev;
}),
filter((ev: KeyboardEvent) => ev.key !== 'Enter' && ev.key !== 'ArrowUp' && ev.key !== 'ArrowDown' && ev.key !== 'Escape'),
debounceTime(this.typeaheadDebounceTime),
distinctUntilChanged(),
tap(() => this.valueChanged.emit(this.searchInput.nativeElement.value)),
takeUntil(this.destroy$)
).subscribe()
}
In mine, I ignored Enter, Up, Down, and Escape so that I could handle those events in a different manner. Also, I call setupTypeaheadObservable()
from the ngOnInit
method. Then it's ready when people start typing. Lastly, I am emitting the value from this component to another one that will call the search service. So you could call the search service directly instead of emitting the event.
Here's a Stackblitz with a working example. The TypeaheadComponent
is where all this code is contained.
Upvotes: 1