bigmadwolf
bigmadwolf

Reputation: 3519

Why is data set with Meteor Iron Router not available in the template rendered callback?

This is a bit puzzling to me. I set data in the router (which I'm using very simply intentionally at this stage of my project), as follows :

Router.route('/groups/:_id',function() {
    this.render('groupPage', {
        data : function() {
            return Groups.findOne({_id : this.params._id});
        }
    }, { sort : {time: -1} } );
});

The data you would expect, is now available in the template helpers, but if I have a look at 'this' in the rendered function its null

Template.groupPage.rendered = function() {
    console.log(this);
};

I'd love to understand why (presuming its an expected result), or If its something I'm doing / not doing that causes this?

Upvotes: 0

Views: 104

Answers (2)

Michael Cole
Michael Cole

Reputation: 16217

From my experience, this isn't uncommon. Below is how I handle it in my routes.

From what I understand, the template gets rendered client-side while the client is subscribing, so the null is actually what data is available.

Once the client recieves data from the subscription (server), it is added to the collection which causes the template to re-render.

Below is the pattern I use for routes. Notice the if(!this.ready()) return; which handles the no data situation.

Router.route('landing', {
  path: '/b/:b/:brandId/:template',
  onAfterAction: function() {
    if (this.title) document.title = this.title;
  },
  data: function() {
    if(!this.ready()) return;
    var brand = Brands.findOne(this.params.brandId);
    if (!brand) return false;
    this.title = brand.title;
    return brand;
  },
  waitOn: function() {
    return [
      Meteor.subscribe('landingPageByBrandId', this.params.brandId),
      Meteor.subscribe('myProfile'),  // For verification
    ];
  },
});

Upvotes: 1

e_m0ney
e_m0ney

Reputation: 980

Issue

I was experiencing this myself today. I believe that there is a race condition between the Template.rendered callback and the iron router data function. I have since raised a question as an IronRouter issue on github to deal with the core issue.

In the meantime, workarounds:

Option 1: Wrap your code in a window.setTimeout()

Template.groupPage.rendered = function() {
    var data_context = this.data;
    window.setTimeout(function() {
        console.log(data_context);
    }, 100);
};

Option 2: Wrap your code in a this.autorun()

Template.groupPage.rendered = function() {
    var data_context = this.data;
    this.autorun(function() {
        console.log(data_context);
    });
};

Note: in this option, the function will run every time that the template's data context changes! The autorun will be destroyed along with the template though, unlike Tracker.autorun calls.

Upvotes: 1

Related Questions