Reputation: 2153
Hi fellow Meteor friends!
Please note: I am using Tom's router!
So I'm trying to only display my template when the mongo collection is ready but for some reason it does not work! :(
I first followed this post: LINK
So I have my publish functions in the server.js and I subscribe to these functions inside my router, so no Deps.autorun() involved here (btw: is this the right approach? Deps.autorun() did not work for me properly):
So I have something like:
'/myroute': function(bar) {
Meteor.subscribe("myCollection", bar, function() {
Session.set('stuffLoaded', true);
});
return 'stuffPage';
}
In the template, where the data loaded from "myCollection" is displayed, I will have something like this:
<template name="stuffPage">
{{#if stuffLoaded}}
<!-- Show the stuff from the collection -->
{{else}}
<p>loading!</p>
{{/if}}
</template>
For some reason "loading!" is never displayed. Also, for a couple of milliseconds, the "old data" from the last time the same template was displayed (but with another "bar" value provided to the publish function --> different data) is displayed.
This of course is not good at all because for a couple of ms the user can see the old data and suddenly the new data appears. To avoid this "flash" I want to display "loading!" until the new data is loaded but again: this does not work for me! :-(
What am I doing wrong?
Thx in advance for your help!
EDIT:
Ok so the problem with the answer in the first post provided by @user728291 is the following:
For some reason the router stuff get's called AFTER the Deps.autorun() ... what is wrong here? :( (please note: eventsLoaded == stuffLoaded.) Where do you guys put your Deps.autorun() for the subscriptions or in other words: What's your code mockup for this?
I actually really think that my code mockup is just plain wrong. So how do you make different subscriptions based on the route (or in other words: based on the template which is currently shown)?
AND: Where do you put the Deps.autorun()? Inside the router.add() function? Or just inside of (Meteor.isClient)?
Upvotes: 1
Views: 1236
Reputation: 3037
I think @user728291's answer is pretty spot on, I'd just add that Meteor.subscribe
returns a handle that you can use to check readiness:
Keep a reference to the handle
Deps.autorun(function() {
stuffHandle = Meteor.subscribe(Session.get('bar'));
});
Then check it in your template:
{{#if stuffHandle.ready}}
...
{{/if}}
Template.barTemplate.helpers({stuffHandle: stuffHandle});
And control it via the session:
'/myroute': function(bar) {
Session.set('bar', bar);
return 'barTemplate';
}
Upvotes: 2
Reputation: 4486
First off, you may be missing the actual function name for the callback as demonstrated in this post.
Meteor.subscribe("myCollection", bar, function onComplete() {
Session.set('stuffLoaded', true);
});
Which seems to be great practice. I don't usually miss a beat using this method.
Secondly, I'm not sure subscriptions inside routes work well? I'd rather do the following:
'/myroute': function(bar) {
Session.set("myCollectionParam", bar)
return 'stuffPage';
}
So then the subsciption finally looks like this:
Meteor.subscribe("myCollection", Session.get("myCollectionParam"), function onComplete() {
Session.set('stuffLoaded', true);
});
OR (not sure which works correctly for you, depending on your publish function):
Meteor.subscribe("myCollection", {bar: Session.get("myCollectionParam")}, function onComplete() {
Session.set('stuffLoaded', true);
});
Good luck!
EDIT
Just mentioning something about the publish function:
While Session.get("myCollectionParam") could return null, you can ensure the behaviour a bit more by using the following publish method:
Meteor.publish("myCollection", function(myCollectionParam) {
check(myCollectionParam, String);
return MyCollection.find({_id: myCollectionParam});
});
Upvotes: 0
Reputation: 4138
Better to put the subscription in a Deps.autorun and use Session variable to pass arguments from the router. Also, make sure you are setting stuffLoaded
to false
before the subscribe runs. Otherwise it just keeps its old value.
'/myroute': function(bar) {
if ( ! Session.equals( "bar", bar ) ) {
Session.set( "stuffLoaded", false); //subscription needs to be run
Session.set( "bar", bar ); // this change will trigger Dep.autorun
}
return 'stuffPage';
}
Deps.autorun ( function (){
Meteor.subscribe("myCollection", Session.get( "bar" ), function() {
Session.set("stuffLoaded", true);
});
});
You might need some initial default values for the Session variables if you are not getting what you want on the first time the page loads.
Upvotes: 2