Skip to content

Instantly share code, notes, and snippets.

@SachaG
Last active March 2, 2016 23:26
Show Gist options
  • Save SachaG/0bc20210c3e2c1e81600 to your computer and use it in GitHub Desktop.
Save SachaG/0bc20210c3e2c1e81600 to your computer and use it in GitHub Desktop.
Template Controller
<template name="postsListController">
{{> posts_list context}}
</template>
// see https://www.discovermeteor.com/blog/template-level-subscriptions/
/*
This template acts as the controller that sets and manages the reactive context
for the embedded postsList template. It receives its parameters from a "caller" template.
*/
Template.postsListController.onCreated(function () {
// 1. Initialization (*not* reactive!)
var instance = this;
// initialize the reactive variables
instance.terms = new ReactiveVar(instance.data.terms);
instance.postsLimit = new ReactiveVar(Settings.get('postsPerPage', 10));
// 2. Autorun
// will re-run when terms are changed, either by the router or by the template itself
instance.autorun(function () {
// get terms from data context
var terms = Template.currentData().terms; // ⚡ reactive ⚡
// get limit from local template variable
var postsLimit = instance.postsLimit.get(); // ⚡ reactive ⚡
// create new subscriptionTerms object using the new limit
var subscriptionTerms = _.extend(_.clone(terms), {limit: postsLimit}); // extend terms with limit
// use this new object to subscribe
var postsSubscription = instance.subscribe('postsList', subscriptionTerms);
var usersSubscription = instance.subscribe('postsListUsers', subscriptionTerms);
var subscriptionsReady = instance.subscriptionsReady(); // ⚡ reactive ⚡
console.log('// ------ autorun running ------ //');
Tracker.onInvalidate(console.trace.bind(console));
console.log("terms: ", terms);
console.log("limit: ", postsLimit);
console.log("ready: ", subscriptionsReady);
// if subscriptions are ready, set terms to subscriptionsTerms
if (subscriptionsReady) {
instance.terms.set(subscriptionTerms);
}
});
});
Template.postsListController.helpers({
context: function () {
var instance = Template.instance();
var terms = instance.terms.get(); // ⚡ reactive ⚡
var postsReady = instance.subscriptionsReady(); // ⚡ reactive ⚡
var postsLimit = terms.limit;
var parameters = Posts.getSubParams(terms);
var postsCursor = Posts.find(parameters.find, parameters.options);
var context = {
// posts cursor
postsCursor: postsCursor,
// posts subscription readiness, used to show spinner
postsReady: postsReady,
// whether to show the load more button or not
hasMorePosts: postsCursor.count() >= postsLimit,
// what to do when user clicks "load more"
loadMoreHandler: function (instance) {
event.preventDefault();
// increase limit by 5 and update it
var limit = instance.postsLimit.get();
limit += Settings.get('postsPerPage', 10);
instance.postsLimit.set(limit);
},
// the current instance
controllerInstance: instance
};
return context;
}
});
@SachaG
Copy link
Author

SachaG commented May 2, 2015

@SachaG
Copy link
Author

SachaG commented May 2, 2015

The advantages of the new pattern over the old one is that the new one is entirely driven by the data context it receives.

So the context helper will reactively update whenever the data context of the template changes. Whereas with the previous pattern, only the internal template instance reactive variables were reactive.

By bringing everything into a single helper, we can also get rid of a few of the variables and simplify the code.

The downside is that since it contains 3 reactive variables the helper might end up re-running reactively 3 or 4 times as each variable changes. Ideally, the posts_list template that's called downstream would be smart enough to not re-render if the data context it's being passed due to context re-running is identical to the previous one. But I'm not sure if that's the case?

Also note that the code could be further simplified by using Percolate's find-from-publication package to restrict the Posts.find() to postsSubscription. This would let us get rid of the two-step subscriptionTerms hack.

@SachaG
Copy link
Author

SachaG commented May 4, 2015

I switched back to the autorun pattern after all. Using Template.currentData() still lets us depend on the parent context though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment