The problem with your solution is that this.searchTerms
is probably an Observable of valueChanges
, so until the value inside the input does not change, any event is being emitted.
Let's say you want to trigger the search each time that the input is being focused, and also each time that the value is changing.
So, in this case, what do you need is to listen to the focus event as well, to be able to emit a value when the focus event is triggered by the input. But you always need to take the last value that valueChanged
emitted. In this case a combineLatest operator would make sense, so you listen to both the focus and the value change. The combineLatest
operator emits the latest values of each source Observables, so even in when the focus
event is the one that emits, you will receive the last one from this.searchTerms
.
To be able to listen to the focus event, you will need to use @ViewChild on your input, to get a reference in your component.
// html
<input ... #myComponent>
// ts
export class MyComponent {
@ViewChild('myComponent') myComponent;
myComponentFocus$: Observable;
constructor () {}
}
Then you can create an observable of the focus event of your input in the ngOnInit function,
ngOnInit(): void {
this.myComponentFocus = Observable.fromEvent(this.myComponent.nativeElement, 'focus')
...
}
Now your bibliographies would be something like:
this.bibliographies = Observable.combineLatest(this.searchTerms, this.myComponentFocus)
.debounceTime(300)
.switchMap(([focusEvt, term]) => term
? this.bibliographieSearchService.search(term)
: this.bibliographieSearchService.search(null, "1", "20"))
.catch(error => {
console.log(error);
return Observable.of<Bibliographie[]>([]);
});
BUT, there is still a problem with this solution. combineLatest
won't emit until all the Observables combined have emitted any value, so our this.bibliographies will still need for the value change to emit before emitting anything.
To solve that, we can create an Observable of null, and then concat this.searchTerms
to this null Observable. This means the new Observable will have a value (null) from the beginning, so when focus
event is emitted, this.bibliographies
Observable will emit as well.
ngOnInit(): void {
this.myComponentFocus = Observable.fromEvent(this.myComponent.nativeElement, 'focus')
this.searchTermsWithNull = Observable.of(null).concat(this.searchTerms)
this.bibliographies = Observable.combineLatest(this.searchTermsWithNull, this.myComponentFocus)
.debounceTime(300)
.switchMap(([focusEvt, term]) => term
? this.bibliographieSearchService.search(term)
: this.bibliographieSearchService.search(null, "1", "20"))
.catch(error => {
console.log(error);
return Observable.of<Bibliographie[]>([]);
});
}
If, for instance, you only want to use the first focus of the event and not all the others, you can add a take(1)
to the focus event observable.