Writing variables to Template.instance().data to avoid needing helpers

In order to get the value of a variable in HTML, Blaze documentation seems to suggest declaring the variable in Template.instance() and returning the value using a template helper function (e.g. return Template.instance().variable).

However it appears that it is possible to access variables in Blaze HTML via Template.instance().data, which would make a template helper function unnecessary.

I have been experimenting with the default “You’ve pressed the button” app and have found that it is definitely possible to discard the template helper function and get the value of the counter reactive variable by writing to Template.instance().data instead of Template.instance() and in the HTML {{counter.get}}.

There are some quirks, however. One is that the template needs to receive at least one name and value pair, regardless of what they are. Below you can see that 0=0 is passed into the hello template. (We could also pass counter=null in order to avoid having 0 as a variable in data.) It seems that this properly initializes the data object in Template.instance(). Without doing this, and trying to initialize data in onCreated (e.g. by writing this.data = { counter: new ReactiveVar(0) }), it fails, as data becomes null elsewhere in the template (e.g. in event handlers).

Here is my simplified fully working version of the Meteor default app that uses no helper function:

<body>
    <h1>Welcome to Meteor!</h1>
    {{> hello 0=0}}
</body>
<template name="hello">
    <button>Click Me</button>
    <p>You've pressed the button {{counter.get}} times.</p>
</template>
Template.hello.onCreated(function helloOnCreated() {
    this.data.counter = new ReactiveVar(0);
});

Template.hello.events({
    'click button'(event, instance) {
        instance.data.counter.set(instance.data.counter.get() + 1);
    },
});

Using this approach (writing to Template.instance().data), it is good that helper functions that simply return variable values are now no longer needed.

However, could there be a way to properly initialize the template’s data object (so that whatever custom variables are set in it (e.g. in onCreated) will still be available elsewhere (e.g. in event handlers and HTML)) without needing to pass any name and value pairs into the template? It would be good if we could just write {{> hello}} instead of {{> hello 0=0}} or {{> hello counter=null}} and have data still fully work as expected.

1 Like

Not sure when this changed but this doesn’t seem to be working anymore.

Meteor 1.7

blaze@2.3.3
blaze-html-templates@1.1.2
blaze-tools@1.0.10
templating@1.3.2
templating-compiler@1.3.3
templating-runtime@1.3.2
templating-tools@1.1.2

Still working for me in every meteor version up to 1.8.0.1
We often add defaults to this.data using underscores _.defaults method

There are a bunch of gotchas though about how this works though.
Like how data props can be reactively re-generated by the parent, discarding the props added directly in the template.
Or if it’s done in a top level template, the onCreated hook runs after rendering, when the data hasn’t been initialised yet.

Happy to take a look in a new thread if you want debugging help

1 Like

template.data is intended to be read only, see the docs.

A simple way to get less verbose with template variables is to define a global instance helper as described by David Weldon using Template.registerHelper.

Also, I recommend reading through his blog, excellent source of ideas.

1 Like