Reputation: 165
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
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