0

i'm getting a list from json which i want to display and being able to filter using an input box. so far it's working but the list only displays once i input something into the searchbox not before that. i would like the list being displayed at the start.I tried to set the search box value at start with empty string but it's not working. looked up the web didn't find the way to achieve. Any help would be appreciated.

my component html:


<h4><label for="search-box">Hero Search</label></h4>

<input #searchBox id="search-box" (input)=search(searchBox.value)  />
<ul class="heroes">
  <li *ngFor="let hero of heroes$ | async">
    <a routerLink="/detail/{{hero.id}}">
      <span class="badge">{{hero.id}}</span> {{hero.name}}
    </a>
    <button class="delete" title="delete hero"
  (click)="delete(hero)">Delete</button>
  </li>
</ul>
<div>
  <label>Hero name:
    <input #heroName />
  </label>
  <!-- (click) passes input value to add() and then clears the input -->
  <button (click)="add(heroName.value); heroName.value=''">
    add
  </button>
</div>

component ts:

  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
  heroes$: Observable<Hero[]>=null;
  heroes: Hero[];
  selectedHero: Hero;
  private searchTerms = new Subject<string>();
  constructor(private heroService: HeroService) {
  }

  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)),
      );


    }

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

  }

  getHeroes(): void {
    this.heroService.getHeroes()
      .subscribe(heroes => this.heroes = heroes);

  }

service ts:

/* GET heroes whose name contains search term */
  searchHeroes(term: string): Observable<Hero[]> {
    if (!term.trim()) {
      // if not search term, return full array.
      return this.getHeroes();
    }
    return this.http.get<Hero[]>(`${this.heroesUrl}/?name=${term}`).pipe(
      tap(x => x.length ?
        this.log(`found heroes matching "${term}"`) :
        this.log(`no heroes matching "${term}"`)),
      catchError(this.handleError<Hero[]>('searchHeroes', []))
    );
  }
2
  • 1
    If you use a BehaviorSubject instead of Subject for searchTerms you can define the inital value while creating the instance: new BehaviorSubject('initial-value-that-should-be-searched-for'). Commented Nov 10, 2020 at 18:06
  • thank you Tom your solution works too : Commented Nov 10, 2020 at 18:25

2 Answers 2

1

You can declare your searchTerms as an BehaviorSubject instead of an simple Subject. The main difference is that as an subcriber of that BehaviorSubject, you will get the last value emitted from that observable no matter when your subscription will happen. Be aware that BehaviorSubject need an initial value that will be emitted when you initialized it.

private searchTerms: BehaviorSubject<string> = new BehaviorSubject<string>('');
Sign up to request clarification or add additional context in comments.

Comments

0

Because in your case it's connected to the input event, you need to automatically trigger a first value to start your pipeline. You can do this by using the startWith operator

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

    startWith(''), // <-- start your pipe with an empty string

    // 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)),
  );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.