带输入的角度异步管道

时间:2020-11-10 18:00:57

标签: html angular typescript

我从json中获取了要显示的列表,并能够使用输入框进行过滤。到目前为止,它仍然有效,但是仅当我在搜索框中输入内容后,列表才显示。我希望列表显示在开始位置。我试图以空字符串开始设置搜索框值,但是它不起作用。 在网上查找并没有找到实现的方法。任何帮助将不胜感激。

我的组件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>

组件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);

  }

服务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 个答案:

答案 0 :(得分:1)

您可以将searchTerms声明为BehaviorSubject而不是简单的Subject。主要区别在于,无论该订阅何时发生,您都将作为该BehaviorSubject的订阅者,获得该可观察对象发出的最后一个值。请注意,BehaviorSubject需要一个初始化时会发出的初始值。

private searchTerms: BehaviorSubject<string> = new BehaviorSubject<string>('');

答案 1 :(得分:0)

因为在这种情况下,它与输入事件有关,所以您需要自动触发第一个值来启动管道。 您可以使用startWith运算符

来完成此操作
  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)),
  );