Kai
Kai

Reputation: 417

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

Upvotes: 0

Views: 109

Answers (3)

Radu Chiriac
Radu Chiriac

Reputation: 1424

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);
});

Upvotes: 1

Ethaan
Ethaan

Reputation: 11376

Use this.

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

Also you subscription should look like this.

Meteor.publish('MyPix', function(cursor) {
    //Counts.publish(this, 'numberOfPosts', MyPix.find(), { noReady: true });
    return MyPix.find({});
});

Also Add, meteor add sacha:spin, because when you have a lot of people, the subscription will be have a little delay.

Add this to each route.

loadingTemplate: "loading"

<template name="loading">
    {{> spinner}}
</template>

Router.onBeforeAction("loading");

Just in case you are showing 100+ images on 'home' and someone enter and have a slow connection, he will think that the page load empty, or something.

Upvotes: 1

Peppe L-G
Peppe L-G

Reputation: 8345

You only subscribe to a subset of all the documents. If you directly go to /doc/tZFawq8cgf43hZBaJ, the document with the id tZFawq8cgf43hZBaJ may not be part of the subset of documents you receive on the client.

Note: if this answer is correct, you should be able to directly go to /doc/<id> for those documents showing up first on the home page (on the first page, when the session variable docCursor is 0).

Upvotes: 0

Related Questions