Agreed that this is old, but figured I’d share a solution I’m pretty happy with currently. Some hacked together ideas that allow you to modify vars from “anywhere”. For clarity’s sake, I’ll call the template with the reactiveVar the dataTemplate
and the template looking to access/modify that var the seekerTemplate
.
Some notes: I typically wrap dataTemplate
s in a ready check, as looking for a reactiveVar (or dict, or function) attached to an external template can result in a race condition, and even though the variable itself is reactive, if the initial lookup fails, then you’re stuck. This is mitigated by the fact that the seekerTemplate
is usually a child of the dataTemplate
. It is possible to use the strategy with sibling templates, but be warned that additional checks may be necessary to guarantee that the template instance is ready.
If anyone is interested, let me know as I’ve been considering documenting some of this stuff out. I’ve been using “components” for a while to access the properties of other templates for a while, and have found it to be pretty helpful.
Also, I’ve found that attaching the display:none
div with a class name that matches the template name gives a reasonably safe method of fetching the template instance from Blaze.getView
, but I’d be interested to hear other approaches.
<!-- client.html -->
<body>
<h1>Welcome to Meteor!</h1>
{{> dataTemplate}}
</body>
<template name="dataTemplate">
<div class="dataTemplate" style="display:none;"></div>
{{#if templateReady}} <!-- any conditionals come after the first div -->
<!-- template stuff -->
<p>Current State: {{ currentState }}</p>
{{> seekerTemplate}}
{{/if}}
</template>
<template name="seekerTemplate">
<p>Current State: {{ getReactiveVar 'dataTemplate' 'currentStateVar' }}</p>
</template>
// client.js
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import './main.html';
Template.dataTemplate.onCreated(function() {
let self = this;
self.currentStateVar = new ReactiveVar(true);
self.templateReadyVar = new ReactiveVar(false);
});
Template.dataTemplate.onRendered(function() {
this.templateReadyVar.set(true);
});
Template.dataTemplate.helpers({
currentState () {
return Template.instance().currentStateVar.get();
},
templateReady () {
return Template.instance().templateReadyVar.get();
}
});
Template.registerHelper('getReactiveVar', function (templateName, varName){
let elem = document.getElementsByClassName(templateName)[0];
if (Blaze.getView(elem)) {
console.log(Blaze.getView(elem));
if (typeof Blaze.getView(elem)._templateInstance[varName] !== 'undefined') {
return Blaze.getView(elem)._templateInstance[varName].get();
} else {
console.log('no reactive var');
}
} else {
console.log('no view');
}
});
For fun in the browser, run:
elem = document.getElementsByClassName('dataTemplate')[0];
Blaze.getView(elem)._templateInstance['currentStateVar'].set('hello, world');