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:
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?
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.