Search code examples
firebasefirebase-realtime-databaseionic3angularfire2angularfire5

Angularfire2 how to combine two list


I am using Angularfire2 v5. In my database I have two lists one is cartand other one is product. In cart list there is a field which contains product id and now I want a Observable that contains data for both the cart and it's product. Currently I am trying with this way

cart: Observable<any>;
constructor(public db: AngularFireDatabase) {}

ionViewDidLoad() {

this.cart = this.db.list(`/cart`)
  .snapshotChanges()
  .map(changes => {
    return changes.map(c => {
      let productObservables:Observable<any> = this.db
        .list(`product/${c.key}`).snapshotChanges()
        .map(m=>{
            m.map(p=>({
              key:c.payload.key, ...p.payload.val()
            }));
            return m;
        });
        return productObservables;
    })
  });

now in html using this

<ion-item *ngFor="let item of cart|async">
  <ion-label>
    {{item.key}}
    {{item.name}}
  </ion-label>

but it shows me null. How can I display both data the cart and product list in one ngFor async


Solution

  • Say you had a structure like this:

    cart:
      yyy:
        productId: aaa
        qty: 2
      zzz:
        productId: bbb
        qty: 1
    products:
      aaa:
        name: AAA
      bbb:
        name: BBB
    

    Then you could map it against the other part of the db, since you already have the key I'm just using valueChanges() here.

    this.cart = this.db.list(`/cart`)
      .snapshotChanges()
      .map(changes => 
        changes.map(c => ({
          key: c.payload.key,
          product: this.db.object(`products/${c.payload.val().productId}`).valueChanges(),
          ...p.payload.val()
        }))
      );
    

    The product will then be async, so you'd need to pipe that in your view too:

    <ion-item *ngFor="let item of cart | async">
      <ion-label *ngIf="item.product | async; let product; else loading">
        {{product.name}} x {{item.qty}} {{item.key}}
      </ion-label>
    <ion-item>
    <ng-template #loading><ion-spinner></ion-spinner></ng-template>