Passing template-level parameters [depreciated]

[PLEASE NOTE]: Depreciating this post, instead please see: Patterns and practices for passing data between templates

I’m building a rudimentary hybrid-messaging-forum application. I just started, and one of the basic things that should happen I suppose is, when one clicks on a post within a list of posts, you should go to the post details.

Using this forum as an example, I would click on a post here:

For reference we can call this the Main screen.

And would be taken to a post detail screen here:

For reference the Detail screen

I’ll have two collections published, one for the Main and one for the Detail screens. The Detail screen of course will need a UserId – but not necessarily the UserId the person logged in. Therefore I’ll store the UserId of the person that created the Post in question in the Detail screen’s collection document.

//Main-Screen.js

{{#each messages}}
  <tr>
  <td>{{detail_screen_user_id}}</td>
  <td>{{post_description}}</td>
  <td>{{last_updated_date}}</td>
</tr>
{{/each}}

This will list out all the users and their posts.

//Detail-Screen.js

{{#each user_post}}
<tr>
  <td>{{post_message}}</td>
  <td>{{post_user}}</td>
  <td>{{last_updated_date}}</td>
</tr>
{{/each}}

This will list out the details of one post.

I need to be able to pass the {{detail_screen_user_id}} to the Detail-Screen template in order to look up the related posts.

The code for the Detail template looks a lot like this:

Template.post_details.onCreated(function () { 
  var self = this;
  self.autorun(function () {
    self.subscribe('user_messages', end_user);
  });
});

Template.post_details.helpers({
  post_details: function (detail_screen_user_id) {
    return user_messages.find({ user_id: detail_screen_user_id }, { sort: { posts: 1 } });
  }
});

I would think that the detail_screen_user_id would need to be pass into the onCreated function for the subscription to filter out the user in the detail screen.

The traditional way to pass an argument over from the Main screen to the Detail screen would be to use a route like so:

Router.route(’/posts’, {name: ‘posts.view’, template: ‘posts’});
Router.route(’/post-detail/:_id’, { name: ‘post.detail.view’, template: ‘posts-detail’ });

Then I’d embed the id in a url and when the user clicks it they’ll get the parameter from the url:

{{#each messages}}
<tr>
  <td><a href="id_goes_here"{{detail_screen_user_id}}</a></td>
  <td>{{post_description}}</td>
  <td>{{last_updated_date}}</td>
</tr>
{{/each}}

Is there another, better way to pass the Id I need from the Main to the Detail screen – one that doesn’t involve the router or the url string as parameters? Also, I’d rather not use global reactive variables (Session), but I’m open to local reactive variables (ReactiveVar).

Don’t take anything I say for granted, but I can tell you how I do it. I use the Blaze.renderWithData() to manually render a template and set it’s data context. That way the id is available in the detail template (view).

I have no experience with Iron Router, but my guess is that somewhere in there, there is a Blaze.renderWithData() as well.

Thanks for the suggestion Ben. I’ll look into how to wire up a solution that fits my needs with Blaze.renderWithData(). But funny thing, I did a search for renderWithData in 1.1.0.2 Meteor docs and couldn’t find a reference to it… why is that?

Did you have it in “full” mode? Direct link (should be) this one http://docs.meteor.com/#/full/blaze_renderwithdata

Ah, that did the trick – I forget about that mode sometimes. Why have the even option…

So, you think that using renderWithData is the best way to pass data (an Id for example), from a ‘Master’ template to a ‘Child’ template? I’m talking about two separate templates here, not one embedded within another.

Why not, as suggested by others, use ReactiveVar or ReactiveDict, or a Session variable even?

No, don’t take this as a best practice :smile: It’s just how I do it. For me this made sense.

The Session… I try to stay far away from it if I can. it might be that I don’t know enough about it, but for me it feels like a fancy global variable. And having a (ancient) history in Flash, that makes me shiver (regarding everybody putting all kinds of stuff in Sessions).

The ReactiveVar… I don’t know how I can reach that ReactiveVar in Template B. But I think that if that was possible, that is fine as well. The fact that that variable is reactive or not, doesn’t matter (in my view). The challenge is reaching the other “template” and being able to talk to it or pass data. Passing it to something that is reactive by itself is not relevant. Same thing for ReactiveDict.

Just in case it matters, I’m also talking to templates that are not related as a parent > child. There are other hacks for that (which for me is bizar that it takes extra Template prototypes to manage, but hey :slight_smile: ).

Getting data out of the template/component is even harder (weird I know). But I use a DOM hack for that (letting my component set it’s data that is accessible to the outside word on the data() property of the firstNode() of the Template instance and reading that out in parent (e.g.) components. As sugar, I also let the component dispatch a jquery event.

But especially the last part about communicating between components is foggy for me. Coming from Flash/Flex it is so getting used to that all these components can only talk to eachother through all sorts of additional tweaks just feels strange.

Hope it helps.

P.S. Just saw the other (almost identical) topic as well. That one has a lot of the same sentiments in it. Is it possible to merge these two threads?

I’m going to see about removing this in order to highlight the other. Just continue the conversation in that thread instead if you don’t mind. The reference thread is here: Patterns and practices for passing data between templates