Using two documents from different collections as data context in one template

I have two collections: Posts and Items
I would like to pass one post- and one item document into the same template simultaneously.

something like:

Template.home.helpers({
  featured: function() {
    return [{ Item.find({_id: featured_id}),
              Posts.find({item: featured_id})
           }];
  }
});

first template:

{{#each featured}}
{{> itemAndPost}}
{{/each}}
</template>```

second template:

```<template name="itemAndPost">
      <div class="text">{{item.text}}</div>
      <div class="footer">
        {{post.name}}
      </div>
</template>```

Of course I could just pass in the item and get the post with a helper, but they both have a lot of fields that I need.
Is this approach possible?

Well,
#each expect cursor or array to iterate in it and provide as data context.
So i dont see problem there as long as you can provide it one.
But both these Item.find and Posts.find are cursors, so probably you need to transform them using "map" or something like that to array of objects, or array of arrays.
But I never tried something like that myself.

but they both have a lot of fields that I need.

what exactly is limiting you to use all fields from both, or I dont understand what you mean by that sentence

I want to use all fields from both documents.
I just meant that using helpers would not be a pretty solution.

Template.home.helpers({
  featured: function() {
    return { 
      item: Items.findOne(featured_id),
      post: Posts.findOne({ item: featured_id })
    }
  }
});
<template name="home">
  {{#with featured}}
    {{> itemAndPost}}
  {{/with}}
</template>

<template name="itemAndPost">
  <div class="text">{{item.text}}</div>
  <div class="footer">{{post.name}}</div>
</template>
2 Likes

Is there a way to do this with two cursors?

eg:

Template.home.helpers({
  featured: function() {
    return { 
      item: Items.find(featured_id),
      post: Posts.find({ item: featured_id })
    }
  }
});

You can’t use a cursor as the value part of an object property. However, you could fetch() each cursor, in which case you’d get an item array and a post array.

Template.home.helpers({
  featured: function() {
    return { 
      item: Items.find(featured_id).fetch(),
      post: Posts.find({ item: featured_id }).fetch()
    }
  }
});

then how do I access the different fields in the template?

well,

item_array = Items.find(featured_id).fetch();
post_array = Posts.find({ item: featured_id }).fetch();

Now merge them however you want and return 1 array consisting from objects which have needed fields from both arrays

But it still seems strange, cause you dont know if these cursors return same number of documents, there can be sorting issues…
But if you really have to be using it this way, why not… you have 2 source arrays, merge them as you want and return 1 array over which you can iterate and each item of that array will have all properties you need.

1 Like

You can do things like this:

<template name="home">
  {{#each featured.item}}
    <div>{{text}}</div>
  {{/each}}
</template>

However, as @shock says, if you want to essentially join the results of two finds together, so a simple helper returns the related parts out of each find, you will have to code that accordingly.