Search code examples
javascriptmeteoriron-router

Single view page permalink empty with Iron Router


I've set up two routes in Iron-Router: 'home' (a paged list of all post) and 'doc' (a detail view). The home page loads just fine, but the detail view can only be loaded if the home page has been viewed previously. Otherwise it will render empty – and it can't be used as a permalink.

This will always load: http://localhost:3000/

This will only load if 'home' has been viewed before: http://localhost:3000/doc/tZFawq8cgf43hZBaJ

the routes:

Router.map(function() {
    this.route('home', {
        path: '/'
    });
    this.route('doc', {
        path: '/doc/:_id',
        data: function() {
            return MyPix.findOne({_id: this.params._id});
        }
    });
});

the doc template:

<template name="doc">
    <h1>{{this.name}}</h1>
    <img src="{{ this.url store='OriginalRetinaPix' }}" width="{{ this.metadata.width }}" height="{{ this.metadata.height }}" />
</template>

publish/subscribe:

Meteor.publish('MyPix', function(cursor) {
    Counts.publish(this, 'numberOfPosts', MyPix.find(), { noReady: true });
    return MyPix.find({}, {sort: {uploadedAt: -1}, limit: 4, skip: cursor});
});

if(Meteor.isClient) {
    Session.setDefault('docCursor', 0);
    console.log('docCursor: ' + Session.get('docCursor'));
    Meteor.autorun(function(){
        Meteor.subscribe('MyPix', Session.get('docCursor'));
    })
}

btw: the project on GitHub


Solution

  • On your "doc" route, you should use the waitOn in order to have the data ready on page load. Add a loading template in the Router.configure as well

    I recommend you to upgrade to the new iron:router routes declarations and also add meteorhacks:subs-manager for better cache on the subscriptions.

    This is an example that should work in your case

    var subs = new SubsManager();
    Router.route('/doc/:_id', {
      name: 'doc',
      template: 'doc',
      waitOn: function() {
        return subs.subscribe('aPix', this.params._id);
      },
      data: function() {
        return {
          apix: MyPix.findOne({
            _id: this.params._id
          })
        };
      }
    });
    

    and on the server side create a publications.js

    Meteor.publish('aPix', function(id) {
      check(id, String);
      return MyPix.find(id);
    });