AngularFirestore Dynami c Запрос - PullRequest
1 голос
/ 14 марта 2020

Я использую Angular 9.0.4 и базу данных Firestore, и у меня есть несколько инструкторов с разными локациями и категориями предмета. Концепция заключается в том, что я выберу свое местоположение и предмет, который я хочу (например, Афины и математика), и я возьму инструкторов с этими ценностями. Я обнаружил, что AngularFire это делает, но некоторые нужные мне операторы «lateLatest »устарели, и, несмотря на то, как сильно я пытаюсь преобразовать код документации с использованием последней версии Rx js, я не могу найти решение. Ниже мой код.

home.component.ts

import {Component, OnInit} from '@angular/core';
import {AngularFirestore} from '@angular/fire/firestore';
import 'firebase/firestore';
import {BehaviorSubject, Observable} from 'rxjs';
import {combineLatest, of} from 'rxjs';
import {map} from 'rxjs/operators';


export interface Instructors {
  last_name: string;
  location: string;
  cate: string;
}


@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
  instructors$: Observable<Instructors[]>;
  locationFilter$: BehaviorSubject<string | null>;
  cateFilter$: BehaviorSubject<string | null>;


  constructor(afs: AngularFirestore) {
    this.locationFilter$ = new BehaviorSubject(null);
    this.cateFilter$ = new BehaviorSubject(null);
    this.instructors$ = combineLatest(
      this.locationFilter$,
      this.cateFilter$
    ).map(([location, cate]) =>
      afs.collection<Instructors>('items', ref => {
        let query: firebase.firestore.Query = ref;
        if (location) {
          query = query.where('location', '==', location);
        }
        if (cate) {
          query = query.where('cate', '==', cate);
        }
        return query;
      }).valueChanges()
    );
  }

  ngOnInit() {

  }

  filterByLocation(location: string | null) {
    this.locationFilter$.next(location);
  }

  filterByCate(cate: string | null) {
    this.cateFilter$.next(cate);
  }

}


home.component. html

<div *ngIf="instructors$ | async; let instructors; else loading">
  <ul>
    <li *ngFor="let instructor of instructors">
      {{ instructor.last_name }}
    </li>
  </ul>
  <div *ngIf="instructors.length === 0">No results, try clearing filters</div>
</div>
<ng-template #loading>Loading&hellip;</ng-template>
<div>
  <h4>Filter by</h4>
  <div>
    <h5>Size</h5>
    <button (click)="filterByLocation('Thessaloniki')">Thessaloniki</button>
    <button (click)="filterByLocation('Crete')">Crete</button>
    <button (click)="filterByLocation(null)" *ngIf="this.locationFilter$.getValue()">
      <em>clear filter</em>
    </button>
  </div>
  <div>
    <h5>Color</h5>
    <button (click)="filterByCate('Leadership')">Leadership</button>
    <button (click)="filterByCate('Maths')">Maths</button>
    <button (click)="filterByCate(null)" *ngIf="this.cateFilter$.getValue()">
      <em>clear filter</em>
    </button>
  </div>
</div>

база данных firestore будет похожа на

instructors{

      randomId{

     name: string;
     cate: string;
     location: string;

     }
}

1 Ответ

1 голос
/ 18 марта 2020

Вы используете оператор map в своем коде, но вам нужно подписаться на новый поток, и в этом случае вам нужно использовать оператор switchMap. Начиная с Rx JS 6.0 (если я не ошибаюсь), вам нужно использовать конвейерные операторы.

Следующий код должен работать:

this.instructors$ = combineLatest([this.locationFilter$, this.cateFilter$]).pipe(
      switchMap(([location, cate]) =>
        afs
          .collection<Instructors>('items', ref => {
            let query: firebase.firestore.Query = ref;
            if (location) {
              query = query.where('location', '==', location);
            }
            if (cate) {
              query = query.where('cate', '==', cate);
            }
            return query;
          })
          .valueChanges()
      )
    );

Примечание: Вы также можете использовать mergeMap и flatMap вместо switchMap. Вы можете прочитать больше о них и о разнице между ними здесь .

...