1
votes

I'm trying to follow the code example in the Angular "Tour-of-Heroes-Tutorial," specifically in the section on setting up an implementation for Search functionality.

My understanding is that the RxJS pipe() function returns a chain of functions that when triggered, will execute. In the case below, the pipe() function is in ngOnInit (in hero-search.component.ts) and returns functions that when executed will return Observables. As such, the heroes$ Observable (in hero-search.component.html and hero-search.component.ts) will contain functions that when triggered will return Hero(es) Observable(s). What I don't understand is: when exactly will the chained functions in heroes$ be triggered? Put another way, what is the event listener in this case, and where is that listener bound to heroes$?

What I see is:
1. The Input in hero-search.component.html is bound to the search() method in HeroSearchComponent.
2. The search() method pushes a new search term into the searchTerms object (an observable stream).

How exactly does this all find its way to heroes$ and cause the functions in heroes$ to be executed?

Many thanks in advance!

(hero-search.component.ts)

export class HeroSearchComponent implements OnInit {
  heroes$: Observable<Hero[]>;
  private searchTerms = new Subject<string>();

  constructor(private heroService: HeroService) {}

  // Push a search term into the observable stream.
  search(term: string): void {
    this.searchTerms.next(term);
  }

  ngOnInit(): void {
    this.heroes$ = this.searchTerms.pipe(
      // wait 300ms after each keystroke before considering the term
      debounceTime(300),

      // ignore new term if same as previous term
      distinctUntilChanged(),

      // switch to new search observable each time the term changes
      switchMap((term: string) => this.heroService.searchHeroes(term)),
    );
  }
}

(hero-search.component.html)

<div id="search-component">
    <h4>Hero Search</h4>

    <input #searchBox id="search-box" (input)="search(searchBox.value)" />

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


</div>

(from hero.service.ts)

    searchHeroes(term: string): Observable<Hero[]>{
        if (!term.trim()) {
            return of([]);
        } 
        return this.http.get<Hero[]>(`${this.heroesUrl}/?name=${term}`).pipe(
            tap(_ => this.log(`found heroes matching "${term}"`)),
            catchError(this.handleError<Hero[]>('searchHeroes',[]))
        );
    }
}
1

1 Answers

2
votes

Since you have used the | async pipe in your code, it automatically subscribes to the observable and this causes the events to execute, so to speak.

Refer : [ https://angular.io/api/common/AsyncPipe ]