实现异步预先搜索的正确方法是什么?

时间:2017-10-23 19:15:29

标签: angular angular-http angular2-observables angular2-ngmodel

在我的Angular应用程序中,有一个“列表”页面。由于有数百个列表,结果一次只加载20个,当用户滚动到底部并点击 More 时会加载更多。

我想在列表上方放置一个搜索框,可以向服务器发送更具体的搜索字词,只返回匹配的列表。

例如,当用户在搜索框中输入“myterm”时,Angular应向GET发送https://myapp.com/listings/?search=myterm,并仅在“商家信息”上显示这些结果页。

我不确定在Angular 2+中执行此操作的正确方法是什么。在AngularJS中,每次按下 Search 时,我都会简单地触发一个返回承诺的新请求,但我怀疑Angular2 +有不同的方法。我似乎无法找到任何关于它的文献。

到目前为止,我刚刚在组件中进行了初始函数调用,该组件使用空搜索参数调用服务(也就是说,获取所有内容)

ngOnInit() {
  this.listings = this.listingService.getListings('');
}

1 个答案:

答案 0 :(得分:1)

我建议使用ReactiveFormsModule,因为解决这个问题真的很容易。

首先,让我们定义我们的FormGroup,它将由一个表单控件组成。

form: FormGroup;

constructor(formBuilder: FormBuilder){
    this.form = formBuilder.group({
        search: ''
    });
}

现在我们已经定义了我们的简单表单,我们感兴趣的是在用户输入时发送请求,所以基本上每当表单控件的值发生变化时。我们可以像这样订阅valueChanges Observable:

ngOnInit(){
    this.form.get('search').valueChanges
       .subscribe(value => this.listingService.getListings(value)));
}

这显然有效,但问题在于我们不想为用户输入的每个字符发送请求。我们要等到他完成了。我们可以使用debounceTime运算符来解决这个问题:

this.form.get('search').valueChanges
       .debounceTime(1000)
       .subscribe(value => this.listingService.getListings(value)));

我们还使用switchMap运算符来避免必须创建一个订阅链(因为getListings也返回一个observable)。我们需要做的最后一件事是添加一个过滤器,因为我们不想发送带有空字符串的请求,假设用户删除了所有键入的内容。我们有filter运算符:

this.form.get('search').valueChanges
       .filter(value => value)
       .debounceTime(1000)
       .switchMap(value => this.listingService.getListings(value))
       .subscribe(listings => this.listings = listings);

模板应与此类似:

<form [formGroup]="form">
    <input type="text" formControlName="search">
</form>