Best-Practise: How to access template.helper-data within template.events?


#1

Hi guys,
I got a newbie question for you:
How do we access helper-data withinin events?

Is this the best pattern? This really seems to be overly complicated
and definetly VIOLATES Dont-Repeat-Yourself!

// INIT REACTIVE-VAR
Template.templateName.onRendered(function() {
  this.syncBetweenHelpersAndEvents = new ReactiveVar();
});

// HELPERS
Template.templateName.helpers({
  'syncBetweenHelpersAndEvents': function() {
    value = MyCollection.findOne()['fieldname'];
    Template.instance().syncBetweenHelpersAndEvents.set(value);  // sync so that EVENTS have access
    return value;  // return for .html
  },
});

// EVENTS
Template.templateName.events({
  'click #button': function (event, template) {
    var valueFromHelper = template.syncBetweenHelpersAndEvents.get();
    // .. process valueFromHelper
  }
});

#2

Hai @thebarty

Why you want to use helper for it? In this case, I would rather use autorun for getting current value:

Template.Foo.onCreated(function () { 
  var self = this;

  this.autorun(function () {
    self.myVal = MyCollection.findOne().fieldName;
  });
});

Template.Foo.events({
   'click #button': function(e, t) {
     console.log(t.myVal);
  });
});

Can you give more information about your problem?

(Btw. don’t set ReactiveVar in onRendered because helper will throw error, that this var does not exist. All reactiveVars should be set in onCreated. The chain for rendering Template is:

onCreated() -> helpers -> onRendered()

endofbtw)


#3

Dear @amigasan,

thanks a lot for the quick response and pointing out the rendering chain! :smile:

I am actually just playing around with some newbie stuff
and found it strange that there is no direct access to a helpers data within an event.

This a stupid example for you that works.
The cool thing about it is that you can actually render multiple Instances of this template
and all would manage their own state.

<template name="exampleDatasourcesReactiveVar">
  <h1>Reactive Variables</h1>
  <input id="nameInput" type="text" value="{{name}}">
  <button id="updateButton">Update</button>
  {{processedName}}
</template>

// TOOLBOX
ReactiveTemplateTools = {
  processName: function (name) {
    return name + ' is not my lover!!';
  }
}

// INIT REACTIVE-VAR
Template.exampleDatasourcesReactiveVar.onCreated(function() {
  this.name = new ReactiveVar();
  this.name.set('Billie Jeans');

  this.processedName = new ReactiveVar();
  this.processedName.set('');
});

// HELPERS
Template.exampleDatasourcesReactiveVar.helpers({
  name: function () {
    return Template.instance().name.get();
  },
  processedName: function() {
    return Template.instance().processedName.get();
  }
});

// EVENTS
Template.exampleDatasourcesReactiveVar.events({
  'input #nameInput': function (event, template) {
    template.name.set(event.target.value);
  },
  'click #updateButton': function (event, template) {
    template.processedName.set(
      ReactiveTemplateTools.processName(template.name.get())
    );
  },
});

#4

I found out that helpers sometimes get called before the template got rendered, so I usually wrap access to template related info

Template.exampleDatasourcesReactiveVar.helpers({
 name: function() {
  var template = Template.instance();
  if(template.view.isRendered) return template.name.get();
  else return null;
})

#5

You can hack it up with
Template.name.__helpers.get('helper').call()