问题
One of the challenges of using a framework that is newish and under development is that the advice you find on the web is often outdated. This applies doubly to Meteor where the SO answers and web articles are often for a pre 1.0.x or an early 1.0.x version, or for the previous version of iron-router, or before they introduced a feature last week, and so on.
Still puzzling over how to use the subscriptionsReady() function in the context of having a template wait until subscriptions are ready for it. I certainly need it since my template tries to render without its data about 3/4 of the time.
How do I use subscriptionsReady()? I've seen examples which use it in the html which I think is kind of dumb (fuzzing presentation and function). How do I use it in the code portion of a template?
Is it used in iron-router with some kind of waitOn? Do I wrap it with a while loop in my template renderer? Can you give a simplified example?
Obligatory code stuff... My route for my template:
Router.route('/', {
path: '/',
template: 'navmenu',
onBeforeAction: function() {
this.next();
}
});
My subscriptions:
// Chapters
ChapterCollection = new Mongo.Collection("ChapterCollection");
if(Meteor.isClient){
Meteor.subscribe('users');
Meteor.subscribe('roles');
Meteor.subscribe('ChapterCollection');
}
The html portion is pretty plain, some HTML wrapped in a template tag.
My template code:
Template.navmenu.rendered = function() {
// Load all chapters from collections
// Unless it decides to delay and then we are *%&@ed
chapterArray = ChapterCollection.find().fetch();
... other stuff ...
}
Thanks for the help.
回答1:
The Iron router way:
Router.route('/', {
name: 'nameOfRoute',
waitOn: function () {
// we will wait for these subsciptions
return [Meteor.subscribe('users'), Meteor.subscribe('roles'), Meteor.subscribe('ChapterCollection')]
},
action: function () {
// this.ready() is true if all items in the wait list are ready
if (this.ready()) {
this.render('yourTemplate');
}
else {
// if not ready, you can render another template in the meantime.
this.render('Loading');
}
}
});
Within the action
function, you may also create template helpers. For example, if one of the subscriptions in the waitOn
function returns documents from a collection called ChapterCollection
, the helper called helperA
will pass this data to the template:
if (this.ready()) {
this.render('yourTemplate', { data: {helperA: ChapterCollection.find()} });
}
html:
<template name="yourTemplate">
//use the #each or #with block with respect to the data being returned. E.g
{{#each helperA}}
{{fieldName}}
{{/each}}
</template>
The Meteor way:
You can use this.subscribe from an onCreated callback to specify which data publications this template depends on
step 1:
So a simple step by step explanation: Once the template has been created, these subscriptions are called. Note here, it's what we do in the template in the step 2. prevents the 'contents' from rendering until the subscriptions are ready
Template.yourtemplate.onCreated(function () {
this.subscribe("users");
this.subscribe("roles");
this.subscribe("ChapterCollection");
});
Step 2:
<template name="yourTemplate">
{{#if Template.subscriptionsReady}}
// all of the template contents here will be rendered ONLY when the subscriptions within the onCreated callbacks are ready.
{{else}}
// if subsciption is not ready, you may show something else here. E.g. "Loading...."
{{/if}}
</template>
回答2:
There is waitOn method for waiting for subscriptions in Iron Router:
Router.route('/', {
name: 'navmenu',
waitOn: function() {
return [
Meteor.subscribe('users');
Meteor.subscribe('roles');
Meteor.subscribe('ChapterCollection');
];
},
onBeforeAction: function() {
this.next();
}
});
So you can remove your subscriptions in your client-side code.
And your "template" option should be "name". Read Iron Router docs.
来源:https://stackoverflow.com/questions/29788763/how-do-i-use-meteor-subscriptionsready-to-ensure-data-is-ready-before-renderin