quince
quince

Reputation: 165

How to filter observable from google firestore

I'm using observable from firestore to fill select list

getInvoices() {
this.invCollection = this.afs.collection('invoices');
this.invoices = this.invCollection.snapshotChanges().pipe(
  shareReplay(1),
  map(actions => {
  return actions.map(action => ({
    key: action.payload.doc.id,
    ...action.payload.doc.data()
  }))
})
)

this.invList = this.invoices.source;

}

And I share data from this.inv observable with this.invList observable

I would like to filter secondone observable based on user selection

<mat-form-field class="ffield">
    <mat-select (selectionChange)="getInv($event)" placeholder="Choose invoice">
      <mat-option *ngFor="let invoice of invoices | async; trackBy: trackByFn" [value]="invoice.key">{{invoice.invNo}}</mat-option>
    </mat-select>
  </mat-form-field>


getInv(e) {
  this.sID = e.value; //id of selected invoice

  //TODO filter this.invList observable   }

I need help with filtering this.invList observable

I did tried something like

this.invList.pipe(map(aaa => {return aaa.map(bbb => ())}), filter(flt => flt.key === this.sID)).subscribe(sss => (console.log(sss.invNo)))

but its not working, property key does not exist

Upvotes: 0

Views: 150

Answers (1)

izmaylovdev
izmaylovdev

Reputation: 1880

rxjs filter operator filter values in the stream (your array is a single value in stream), in your case you don't need filter values in stream, you need map array of values to specific value by ID.

this.invoices$ = this.invCollection.snapshotChanges().pipe(
  map(actions => 
    actions.map(action => 
      ({
        key: action.payload.doc.id,
        ...action.payload.doc.data()
      })
    )
  )
)

if you need to create stream with element by specific id:

getInvoiseById(id): Observable<InvoiceType> {
 return this.invoices$.pipe(
   map(invoices => 
     invoices.filter(({key}) => key === id)))
   )
}

if you need to create stream with active invoice, better way is create stream with active ID and combine it with invoice's stream

activeId$ = new Subject<TypeOfIdField>();

activeInvoice$ = combineLatest([
  this.invoices$,
  this.activeId$
]).pipe(
  map(([invoices, id]) => 
    invoices.find(({key}) => key === id)
  )
)

setActiveId(id) {
  this.activeId$.next(id);
}

Notice: If you want use shareReplay, better move it to the end of pipeline, in your code you first cache your initial data and after that map it to used format, in this case you transform the data for every subsription, if you move shareReplay to the end of pipeline, you cache already transformed data

Upvotes: 1

Related Questions