6

I'm building an experimental (Ionic 2) app that uses Firebase and AngularFire2 (currently in alpha). For this I'm following this tutorial from Aaron Saunders as a basis:

http://www.clearlyinnovative.com/integrating-firebase-with-angularfire2-into-angular2-ionic2-part-2 https://github.com/aaronksaunders/ionic2-angularfire-sample

Below are my home.ts and my home.html.

this.projects = af.list('/items').map( (items) => {
    return items.map( item => {
        item.meta = af.object(`/item_meta/${item.$key}`)
        return item
    })
})

This way of nesting the Observables returns by AngularFire2 was demonstrated in the following presentation: https://youtu.be/ngnSOTSS8Q8?t=1h6m37s

Here is my view:

<ion-card *ngFor="#item of items | async">
    <ion-card-header>
        {{item.name}}
    </ion-card-header>
    <ion-card-content>
        {{item.description}}
        <br>

        {{item.meta.stockPrice | async}}

    </ion-card-content>
</ion-card>

The main difference with the example in the presentation I followed is the fact that I'm nesting an 'object' Observable inside an 'list/array' Observable. Instead they add a list within a list. The consequence of this is that I'm trying to render {{ item.meta.stockPrice }} in my view directly instead of nesting an ngFor.

This is what my data looks like:

{
    "items":
        {
            "item1":{
                "name": "Item 1",
                "description": "1234"
            },
            "item2":{
                "name": "Item 2",
                "description": "abcd"
            }
        }
    "items_meta"{
        "item1":{
            "stockPrice": 1234,
            "moarData": "derp"
        },
        "item2":{
            "stockPrice": 386,
            "moarData": "lolz"
        }
    }
}

I can't seem to figure out why object doesn't want to render. If I output it to JSON it shows that the data is there. Please note that I am new to Angular2 and still wrapping my head around the changes from Angular1. What am I doing wrong?

Edit: I've update the info above and added my data structure to make it more clear

DivZero
  • 2,438
  • 2
  • 24
  • 23

1 Answers1

17

For your specific issue...

{{(item.meta | async)?.stockPrice}}

use the elvis operator (?) to make sure the async operation is complete and then access the desired value

source code here in github: https://github.com/aaronksaunders/afwithngcli

--

you got ahead of me... working on the new blog post, but here is the code

script.html

</ion-card>
    <ion-card *ngFor="#user of usersWithMessages | async">
    <ion-card-header>
        {{user.displayName}}
    </ion-card-header>
    <ion-card-content>
       {{ (user.messages | async) | json}}
    </ion-card-content>
</ion-card>

script.ts

this.usersWithMessages = this.af.list('/users').map((_users) => {
    return _users.map((_user) => {
        _user.messages = this.af.object("/userObjects/public-messages/" +_user.$key)
        return _user
    })
})

data

   "userObjects" : {
    "public-messages" : {
      "8d75a63e-80cd-40cc-8f8b-87d3d33b0cd0" : {
        "message-id-0" : {
          "text" : "a public message"
        }
      },
      "9c6ea912-ec24-4127-b123-6512ed135f06" : {
        "-KFCGp5ojo7JSX2myOPE" : {
          "date" : "1460511658442.75",
          "text" : "this should be a. public message"
        },
        "-KFCJc4GtEo_PDWi7hru" : {
          "date" : "1460512391529.69",
          "text" : "this is a message that should be public"
        },
        "message-id-100" : {
          "date" : "3243245411111",
          "text" : "public for the other user"
        }
      }
    }
  },
 "users" : {
    "8d75a63e-80cd-40cc-8f8b-87d3d33b0cd0" : {
      "displayName" : "c@mail.com",
      "provider" : "password"
    },
    "9c6ea912-ec24-4127-b123-6512ed135f06" : {
      "displayName" : "b@mail.com",
      "provider" : "password"
    },
    "cdcf32af-a8cd-467d-a04f-dfc223e890d2" : {
      "avatar" : "https://secure.gravatar.com/avatar/d23563ab3014ce965a90c37b22a34da8?d=retro",
      "displayName" : "bryce@mail.com",
      "provider" : 4
    }
  }
Aaron Saunders
  • 33,180
  • 5
  • 60
  • 80
  • maybe I'm overlooking something but I think my code is basically the same. If you change your code to: {{ (user.messages.message-id-100.text | async}} does this work? For me it gives an error. Printing it as JSON works just fine. However I have known keys (for example: user.lastActivity.name ) and need to render the value in the view as text (for example: gaming). – DivZero May 06 '16 at 13:53
  • Great work on the blog posts btw, it was a great starting point! Please be advised that things are breaking if you try to up update. Angular 2 just moved into RC, Ionic 2 has a separate branch moving to the Angular RC and AngularFire just went into beta (with better docs and querying) which requires the Angular RC. However they don't play nice together yet ;-) – DivZero May 06 '16 at 13:54
  • what exactly are you trying to do... `(user.messages.message-id-100.text | async}} ` will not work because it is not an observable... and you are asking multiple questions at the sametime which make it difficult to answer your question... you need to provide more information on your data structure – Aaron Saunders May 06 '16 at 14:58
  • I've edited my post to make more clear what I am looking to achieve and added my data structure. I've separated these because stockPrice will update very often. – DivZero May 06 '16 at 18:03
  • see updated answer with your specific problem resolved – Aaron Saunders May 10 '16 at 13:40
  • Thank you so much. I knew it had to be easy. But couldn't figure out the syntax. – DivZero May 11 '16 at 09:50
  • Hey @Aaron Saunders/@DivZero, is it possible to return the `_user.messages` as an array and not as observable? – TheUnreal Nov 20 '16 at 17:03