How to only execute an Observable if term is not null/empty?

21,493

Solution 1

If you want to avoid the API call and want the search results to be reset when the search term is empty, test for an empty string in switchMap and return an empty observable in that situation:

this.searchResults = this.searchTerm
  .valueChanges
  .debounceTime(500)
  .distinctUntilChanged()
  .switchMap(term => term ?
    this.apiService.search({
      limit: this.searchResultsLimit,
      term: term
    }) :
    // If search term is empty, return an empty array
    // or whatever the API's response for no matches
    // would be:
    Observable.of([]) 
  });

Solution 2

Most easily just use the filter() operator to filter out all empty terms:

this.searchResults = this.searchTerm.valueChanges
    .filter(term => term) // or even better with `filter(Boolean)`
    .debounceTime(500)
    .distinctUntilChanged()
    .switchMap(term => this.apiService.search({
        limit: this.searchResultsLimit,
        term: term
    }));

Solution 3

In Rxjs 6 so updated to use pipe you can stop the observable from processing so nothing is propagated downstream using EMPTY:

this.searchResults = this.searchTerm.valueChanges
    .pipe(
      debounceTime(500)
      distinctUntilChanged()
      switchMap(term => 
        (term) 
          // If the term exists make a request
          ? this.apiService.search({ limit: this.searchResultsLimit, term: term })
          // Otherwise, stop all processing
          : EMPTY
      )
    )
);
Share:
21,493
Fizzix
Author by

Fizzix

Full-stack Javascript developer. I specialize in Angular and NodeJS.

Updated on September 24, 2020

Comments

  • Fizzix
    Fizzix over 3 years

    I have the following code inside my constructor:

    this.searchResults = this.searchTerm.valueChanges
        .debounceTime(500)
        .distinctUntilChanged()
        .switchMap(term => this.apiService.search({
            limit: this.searchResultsLimit,
            term: term
        }));
    

    And this is my input

    <input type="text" [formControl]="searchTerm" />
    

    You can see the tutorial I followed to get the code here.

    My API service method is as followed:

    searchCompanies(options): Observable<any[]> {
        return this.jsonp.get('api/search', this.formatOptions(options)).map(res => {   
            return res.json();
        });
    }
    

    Each time searchTerm is changed inside my input, the API call is fired. My problem is that the call is fired even when my input is empty (such as typing a query, then backspacing it all).

    My question is, how can I only get my observable to fire when the value of `searchTerm is not empty/null?