2

I'm looking for a way to get the methods of a child element instead of loading that element separately.

Let's say I have a Post model and each post has comments. This is how I get the post model:

var post = $firebase(new Firebase(FIREBASE_URL + "/posts/" + post_name)).$asObject();

Each post has comments so I can access the comments using:

post.$loaded(function () {
  var comments = post.comments;
}

Now how do I push a new element to comments without having to load the model separately from Firebase? I should be able to do the following but it doesn't work:

comments.$add({text: "Hi, there"});

Is there any proper way to get the firebase methods of a child element without having to go back to the server and get the comments?

Maher Manoubi
  • 585
  • 1
  • 6
  • 18
  • Firebase will load the data only once. After that you can construct as many refs on it as you like, without downloading the data again. So in this case, simply pull down the `comments` as an `$asArray()` too. – Frank van Puffelen Oct 07 '14 at 10:50
  • I have tried $asArray() with post.comments.$asArray() and it didn't work. The reason I asked this question is because I didn't want to download the data again to be able to perform actions but if I cannot find any other way, I may end up doing just that. – Maher Manoubi Oct 07 '14 at 20:50
  • 1
    As I already said: Firebase will download the data only once, no matter how many refs you create to it. But `post.comments.$asArray()` will not work, since your `post` is a plain JavaScript object (and not a `$firebase` sync anymore). Instead try `$firebase(new Firebase(FIREBASE_URL + "/posts/" + post_name + "comments")).$asArray();` – Frank van Puffelen Oct 07 '14 at 22:05
  • Wrote it up in an answer too, which allows some more explaining. – Frank van Puffelen Oct 07 '14 at 22:12

1 Answers1

7

Firebase will load the data from the server only once. After that your JavaScript code can construct as many refs on it as you need, without downloading the data again.

But post.comments.$asArray() will not work, since your post is a plain JavaScript object (and not a $firebase sync anymore).

Instead try:

var ref = new Firebase(FIREBASE_URL + "/posts/" + post_name);
var post = $firebase(ref).$asObject();
var comments = $firebase(ref.child("comments")).$asArray();

Consider an alternate data structure

But you may want to reconsider your data structure. Even though Firebase is a hierarchical data store, they recommend against building deeply nested hierarchies. See Avoid Building Nests on https://www.firebase.com/docs/web/guide/structuring-data.html

Because we can nest data up to 32 levels deep, it's tempting to think that this should be the default structure. However, when we fetch data for a node in Firebase, we also retrieve all of its child nodes. Therefore, in practice, it's best to keep things as flat as possible, just as one would structure SQL tables.

So in your case that could lead to having two top-level elements posts and comments.

root
  posts
    post1
    post2
  comments
    post1
      post1comment1
      post1comment2

And you can then simply load the post and its comments with:

var root= new Firebase(FIREBASE_URL);
var post = $firebase(root.child("posts").child(post_name)).$asObject();
var comments = $firebase(root.child("comments").child(post_name)).$asArray();
riper
  • 833
  • 1
  • 9
  • 17
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807