【问题标题】:Need to load all items to Observable<Hero[]> before the users add any filter需要在用户添加任何过滤器之前将所有项目加载到 Observable<Hero[]>
【发布时间】:2017-11-15 06:38:49
【问题描述】:

如何更改 Angular 2 Tour of Heroes 搜索组件 (https://angular.io/generated/live-examples/toh-pt6/eplnkr.html),以便它在初始化时带来所有项目(在页面加载时显示所有英雄),并且当提供过滤器时,它会向服务发出新请求过滤后的结果放入 heros 变量中?

import { Component, OnInit } from '@angular/core';
import { Router }            from '@angular/router';

import { Observable }        from 'rxjs/Observable';
import { Subject }           from 'rxjs/Subject';

// Observable class extensions
import 'rxjs/add/observable/of';

// Observable operators
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';

import { HeroSearchService } from './hero-search.service';
import { Hero } from './hero';

@Component({
  selector: 'hero-search',
  templateUrl: './hero-search.component.html',
  styleUrls: [ './hero-search.component.css' ],
  providers: [HeroSearchService]
})
export class HeroSearchComponent implements OnInit {
  heroes: Observable<Hero[]>;
  private searchTerms = new Subject<string>();

  constructor(
    private heroSearchService: HeroSearchService,
    private router: Router) {}

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

  ngOnInit(): void {
    this.heroes = this.searchTerms
      .debounceTime(300)        // wait 300ms after each keystroke before considering the term
      .distinctUntilChanged()   // ignore if next search term is same as previous
      .switchMap(term => term   // switch to new observable each time the term changes
        // return the http search observable
        ? this.heroSearchService.search(term)
        // or the observable of empty heroes if there was no search term
        : Observable.of<Hero[]>([]))
      .catch(error => {
        // TODO: add real error handling
        console.log(error);
        return Observable.of<Hero[]>([]);
      });
  }

  gotoDetail(hero: Hero): void {
    let link = ['/detail', hero.id];
    this.router.navigate(link);
  }
}

目前只是在提供搜索词后发送请求。

【问题讨论】:

  • 所以你想查看所有英雄而不是顶级英雄,我说对了吗还是我误解了你的问题?
  • 我不需要更改 Top Heroes 的行为,我只需要默认显示所有英雄的列表,当输入内容时,列表会被过滤。
  • 我尝试在ngOnInit() 中添加对this.search(""); 的调用,但似乎没有任何反应(服务未执行)。

标签: angular


【解决方案1】:

你好_

基本上这是您可以进行更改以使其正常工作的主要地方:

.switchMap(
    term => term    
    ? this.heroSearchService.search(term)
    : Observable.of<Hero[]>([]))  // <----- HERE if term is empty string you want to return all Heroes instead of empty collection 

要实现这一点,您可以从 hero.service.ts 注入 HeroService,该方法具有返回所有英雄的方法 getHeroes()

所以现在我们可以把上面的代码改成这样:

// First don't forget to inject HeroService and don't forget to import it too
constructor(
    private heroSearchService: HeroSearchService,
    private heroService: HeroService,
    private router: Router) {}

// Then the ngOnInit() will look like this
ngOnInit(): void {
    this.heroes = this.searchTerms
      .debounceTime(300)        
      .distinctUntilChanged()  
      .switchMap(term => term  
        ? this.heroSearchService.search(term)
        : this.heroService.getHeroes()) // <--- HERE if term is empty return all heroes
      .catch(error => {
        console.log(error);
        return Observable.of<Hero[]>([]);
      });

      // Wait for 100 ms before loading all heroes ...
      setTimeout(() => {
        this.search('');
      }, 100); 
} 

我尝试添加对 this.search(""); 的调用在 ngOnInit() 内部

是的,我们需要这个来加载所有英雄,但是稍微延迟一下,否则什么都不会显示。

如果一切都清楚,请告诉我:)

【讨论】:

  • 感谢您的回答。但是我们没有办法在没有 setTimeout 的情况下调用search() 方法吗?
  • 嗯,这对我来说似乎是一个时间问题,用setTimeout() 调用它似乎很好。我现在正在考虑的另一件事是实现AfterViewInit 并在ngAfterViewInit() 内调用this.search(''),但这未经测试你可以尝试并报告结果是什么
  • 这看起来像是一个更“优雅”的解决方案。谢谢
  • 我应该明白它有效吗:) 不客气
  • 完美运行:)
猜你喜欢
  • 1970-01-01
  • 2013-09-05
  • 2018-03-29
  • 1970-01-01
  • 1970-01-01
  • 2013-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多