Question

I am using Iron-Router with Meteor. When the user goes to /foo/:routeID, it's important that the foo is loaded before they arrive. Sometimes it doesn't get loaded in time though and the page will render wonky. I haven't been able to figure out a discernible pattern to when these times occur.

If I change it such that the page re-renders after the foo is loaded, then there's a noticeable update. I'd rather just have it s.t. the page renders when the foo object is loaded. How do I make this so? My current routing is below.

this.route('foo', {
    path:'/foo/:routeID',
    layoutTemplate:'base',
    before: function() {
        foo = Foos.findOne({routeID:this.params.routeID});
        console.log('before');
        console.log(foo);
        Session.set('foo', foo);
    }
Was it helpful?

Solution

When you are using IronRouter, Before will always run, but it won't always block, so if something takes a while, your other code could still end up running too early.

In order to make sure that your collection is loaded, you need to call .wait() on it to force Meteor/IronRouter to not try to display the template or run other relevant code until after the collection has loaded.

Something like this should work:

this.route('foo', {
path:'/foo/:routeID',
layoutTemplate:'base',
before: function() {
    this.subscribe('foos').wait();
    foo = Foos.findOne({routeID:this.params.routeID});
    console.log('before');
    console.log(foo);
    Session.set('foo', foo);
}

You will need to make sure that you have a publish function defined as well (and turn off autopublish if you haven't yet) for foo.

EDIT: Additionally, for security and to prevent all users/routes from downloading every Foo and then filtering on the client side you can use a publish/subscribe function with a param to make sure you aren't downloading the entire collection each time you hit a page.

this.subscribe('foos', this.params.routeID).wait();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top