Issue
I have integrated stripe into my firebase project (Firestore) which through web hooks adds and updates the products I have setup in Stripe to the firestore database. To display available products I have an observable which is subscribed in the template using async pipe. This all works fine, however, each product document in the products collection has a sub collection called ‘prices’ which contains the current and previous prices. I am trying to figure out how to return this additional data for each product in the main products observable.
The code to return just the products is:
export interface Item { name: string; id: string; }
watchProducts () {
const productsCollection: AngularFirestoreCollection<Item> =
this._firestore
.collection('products', ref => {
return ref.where('active', '==', true);
});
const currentProducts: Observable<Item[]> = productsCollection.snapshotChanges().pipe(
map(actions => actions
.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
console.log('a.payload');
console.log(a.payload);
return { id, ...data };
}),
),
);
return currentProducts;
}
The template code is:
<button *ngFor="let product of products | async" ">
{{product.name}} £/ month
</button>
The location of the prices collection is:
this._firestore
.collection('products')
.doc({productId})
.collection('prices', ref => {
return ref.where('active', '==', true);
})
I would like to merge the results so in the async ngFor I could access the current price with active === true. I’ve looked at switchMap and mergeMap but can’t seem to get anything to work properly. My knowledge is RxJs is somewhat limited.
Any help would be greatly appreciated.
Best A
Solution
You can create your own operator
as Jeff introduced. But to simplify, you could manage it as following way:
const products$ = this._firestore
.collection('products')
.snapshotChanges()
.pipe(
map((actions: any[]) => actions.map((a) => ({ ...a.payload.doc.data(), ...{ id: a.payload.doc.id } }))),
switchMap((products: any[]) => {
const pricesCols$ = products.map((p) =>
this._firestore
.collection(`products/${p.id}/prices`, (ref) => ref.where('active', '==', true))
.valueChanges()
);
// passing the products value down the chain
return combineLatest([of(products), combineLatest(pricesCols$.length ? pricesCols$ : [of([])])]);
}),
map(([products, pricesCols]) =>
products.map((p, idx) => {
p.prices = pricesCols[idx];
return p;
})
)
);
Answered By – coturiv
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0