Accessing Template specific variables from other Templates


#1

I always liked the new way of encapsulating reactive vars inside the template instead of using global variables (Session) by specifying it in the onCreated phase

Template.myTemplate.onCreated(function(){
 var instance = this;
 instance.someReactiveVar = new ReactiveVar(false);
 instance.autorun(function(){
  var someReactiveVar = instance.someReactiveVar.get();
  instance.subscribe('collection', someReactiveVar);
 });
});
Template.myTemplate.helpers({
 helper: function() {
  var instance = Template.instance();
  return instance.someReactiveVar.get();
});
Template.myTemplate.events({
 'click button': function(event,instance) {
  instance.someReactiveVar.set( 'value' );
 }
});

etc.

Unfortunately this way you can never modify a value from outside myTemplate.

Today I had this epiphany that Template.myTemplate is a global variable, so I figured out to do the following

Template.myTemplate.someReactiveVar = new ReactiveVar(false);

Template.myTemplate.onCreated(function(){
 var instance = this;
 instance.autorun(function(){
  var someReactiveVar = instance.view.template.someReactiveVar.get();
  instance.subscribe('collection', someReactiveVar);
 });
});
Template.myTemplate.helpers({
 helper: function() {
  var instance = Template.instance();
  return instance.view.template.someReactiveVar.get();
});
Template.myTemplate.events({
 'click button': function(event,instance) {
  instance.view.template.someReactiveVar.set( 'value' );
 }
});

But now I can modify that value from anywhere

Template.otherTemplate.helpers({
 helper: function() {
  Template.myTemplate.someReactiveVar.set( 'value' );
 }
});

This allowed me to clean up my code a lot.

I thought I’ld share. What do you think?


#2

Been there, done that, got the t-shirt. It ain’t such a hot idea.

You’re creating an implicit dependency between your templates. I often use this analogy: The problem here is that you want to share a banana but you end up sharing the gorilla holding the banana, and keeping track of the entire gorilla tribe.

In more concrete terms, you want to share a value but end up sharing the whole template instead. You then have to keep track of who references who. If you change a template you might break another inadvertently.

The fact of the matter is that you will have a global object that holds the state you want to share. In your case it’s Template.myTemplate. I would recommend having a global dictionary used specifically to share small pieces of state between your templates. You still keep the state in your template but the shared value is available to anyone who wants to access it.

That way your templates are kept separate. Changing one doesn’t affect another.


#3

But what do you do if you have the template multiple times on your site (f.e. a list) and you only want to change the value of the template with id 123? I don’t think that this will fit your needs. I would recommend you to use ViewModel instead, there you can do something like this:

ViewModel.findOne('mytemplate').aMethod()

Or in my case above:

ViewModel.find('mytemplate').forEach((temp)=> { if(temp.id()==123) .....});

#4

Thanks for responding. I certainly value your feedback and will look at the bananas in my zoo :slight_smile: