Search code examples
angularrxjsangular2-observables

Return all results if no search parameter is given


I was looking at the declarative RxJS approach to tour of heroes by Deborah Kurata. I would like to know how it would work in the following case:

  1. By default, load all heroes
  2. If there's a search term, show the search results

Now, this would be probably possible by doing something like this:

hero-search.component.ts:

  export class HeroSearchComponent {
  // DJK3 Assign to the declared Observable in the service
  heroes$ = this.heroService.filteredHeroes$;
  allHeroes$ = this.heroService.heroes$;

  searchActive = false;

  constructor(private heroService: HeroService) {}

  // Push a search term into the observable stream.
  search(term: string): void {
    this.heroService.search(term);
    this.searchActive = true;
  }
}

hero-search.component.html:

<div id="search-component">
  <label for="search-box">Hero Search</label>
  <input #searchBox id="search-box" (input)="search(searchBox.value)" />

  <ng-container *ngIf="!searchActive; else searchResults">
    {{allHeroes$ |async | json}}
  </ng-container>


  <ng-template #searchResults>
    <ul class="search-result">
      <li *ngFor="let hero of heroes$ | async">
        <a routerLink="/detail/{{hero.id}}">
          {{hero.name}}
        </a>
      </li>
    </ul>
  </ng-template>

</div>

But this looks wrong to me. Is there a better approach? Maybe checking this directly in the service?


Solution

  • How many heroes?

    If not too many, then I'd imagine allHeroes$ to be created by a service that, internally, would be something like this.httpClient.get(methodName, options).pipe(shareReplay(1)) and then have a method on the service that accepted an Observable<string> and returned combineLatest([this.allHeroes$, arg]).pipe(map(([heroes, searchTerm]) => !searchTerm ? of(heroes) : heroes.filter(insertFormulaHere))) (... at least initially, but this could be optimized after a working prototype was achieved.)

    Then, the component would instantiate an observable that listened to changes to the search box, and pass it to the service method, saving the response to the component's heroes$ property.