Angular + Firestore 自动完成

标签 angular google-cloud-firestore observable

我的网站上有一个自动完成搜索栏。它是用 Angular 7 构建的,信息来 self 的 Firestore 数据库。目前,当用户键入时,搜索栏不会过滤选项。 onLoad() 函数应该对我的 Schools 集合进行一次提取,并在用户输入时筛选该集合。

搜索栏代码

      <form>
        <mat-form-field style="width: 50vw; max-width: 400px;" appearance="outline">
          <input matInput placeholder="Search schools..." aria-label="School" [matAutocomplete]="auto" #schoolInput [(ngModel)]="searchModel" (keyup.enter)="searchButton(schoolInput.value)" name="inputField" id="searchInput">
          <mat-icon class="searchIcon" matSuffix style="color: #6336c6;" (click)="searchButton(schoolInput.value)">search</mat-icon>
          <mat-autocomplete #auto="matAutocomplete">
            <mat-option *ngFor="let school of schools | async" [value]="school.name">
              <span class="ui tiny header">{{ school.name }}</span>
              <span *ngIf="school.country == 'United States'; then withState else withoutState"></span>
              <ng-template #withState><small> {{school.city}}, {{school.state}}</small></ng-template>
              <ng-template #withoutState><small> {{school.city}}, {{school.country}}</small></ng-template>
            </mat-option>
            <mat-option *ngIf="user" (click)="openDialogAddSchool()" style="font-style: italic; padding-bottom: 4px; margin-bottom: 12px;">
              <button class="ui basic fluid violet button" style="margin-top:6px;"><i class="plus icon"></i>Add school</button>
            </mat-option>
          </mat-autocomplete>
        </mat-form-field>
      </form>

到目前为止的 TS 代码

fetchSchools(){

    this.schoolsCollection = this.afs.collection('Schools', ref => {
      return ref.orderBy('name');
    });

    this.schools = this.schoolsCollection.valueChanges();

    console.log('Retreived schools:');
    console.log(this.schools);

  }

回应 检索学校:

page-home.component.ts:308 Observable {_isScalar: false, source: Observable, operator: MapOperator}

enter image description here

最佳答案

我会推荐一个服务,通常我们使用一个服务来处理 http 调用,在本例中是 firebase 查询。因此,我将创建服务,创建一个 schools 变量,如果它有值(value),则返回它的可观察值,或者然后从 firebase 查询返回结果,除非您想始终查询数据库,但这会变得非常昂贵。

schools = [];

fetchSchools() {
  if (this.schools && this.schools.length) {
    return of(this.schools)
  } else {
    return this.afs.collection('Schools', ref => {
      return ref.orderBy('name')
    }).valueChanges().pipe(
        tap((schools) => this.schools = schools)
      );
  }
}

组件将订阅此数据,并在数据被过滤后将数据分配给可观察对象。我喜欢添加一个 debounceTime:

filterSchools() {
  this.schoolsObs = this.myService.fetchSchools().pipe(
    debounceTime(300),
    map((data) => this.performFilter(data))
  )
}

然后您可以选择如何完成过滤...使用startsWithincludes (??)。还要选择您想要过滤的 Prop 。我的示例如下所示:

performFilter(schoolsObs) {
  return schoolsObs.filter((x) => {
    // filter by what prop you want
    return x.name.toLowerCase().startsWith(this.searchModel.trim().toLowerCase())
  })
}

最后对于模板,我会监听用户的输入:

<input 
  matInput 
  [matAutocomplete]="auto" 
  (input)="filterSchools()" 
  [(ngModel)]="searchModel"
>

演示: StackBlitz

关于Angular + Firestore 自动完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57564756/

相关文章:

Angular2 如何更新可观察集合中的项目

angular - 数字管道的参数是什么 - Angular 2

angular - 如何命名 Angular 中的 _nghost/_ngcontent Prop ?

arrays - 在 Javascript/Typescript 中克隆一个数组

angular - 如何将带有按钮的列添加到带有循环的表格中?

javascript - 获取所有鼠标点击的 Rx 流的可移植方法

java - Android 的 Firestore 超时

firebase - 如何使用 flutter cloud_firestore 包传递 firestore 身份验证 token

android - Firestore 查询 - 一对多关系

java - 将 Observable/Observer 与两个不同的双变量一起使用?