Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meteor: Access Template Helper (or variable) from another helper

How can I reference a template helper from another one? For example...

Template.XXX.helpers({
    reusableHelper: function() {
        return this.field1 * 25 / 100; //or some other result
    },
    anotherHelper: function() {
        if (this.reusableHelper() > 300) //this does not work
            return this.reusableHelper() + ' is greater than 300'; 
        else
            return this.reusableHelper() + ' is smaller than 300';
    }
});

I have also tried Template.instance().__helpers.reusableHelper - all with no luck.

Alternatively is there a way to define reactive Template instance variables?

XXX is a sub-template that renders multiple times on the same page.

like image 878
Habib Avatar asked Jan 29 '15 10:01

Habib


3 Answers

You can but only with global template helpers.

Blaze._globalHelpers.nameOfHelper()

Here is an example calling Iron:Router's pathFor global helper.

Template.ionItem.helpers({
  url: function () {
    var hash = {};
    hash.route = path;
    hash.query = this.query;
    hash.hash = this.hash;
    hash.data = this.data;
    var options = new Spacebars.kw(hash);

    if (this.url){
      return Blaze._globalHelpers.urlFor(options)
    } else if( this.path || this.route ) {
      return Blaze._globalHelpers.pathFor(options)
    }
  }
});

EDIT: To your second question. You can call the same template as many times as you like on a page and pass different data attributes directly into it and/or use #each block template wrapper to iterate over data. #each will call a template many times giving it a different data context each time.

#each Example

<template name="listOfPosts">
  <ul>
    {{#each posts}}
      {{>postListItem}} <!--this template will get a different data context each time-->
    {{/each}}
  </ul>
</template>

Attributes Example

<template name="postDetails">
  {{>postHeader title="Hello World" headerType="main" data=someHelper}}
  {{>postHeader title="I am a sub" headerType="sub" data=newHelper}}
  {{>postBody doc=bodyHelper}}
</template>
like image 90
benstr Avatar answered Oct 15 '22 00:10

benstr


This like using of common code, you can make another javascript function which contains the your reusable code and call it from wherever you required.

Like in your code-

function calcField(field){
   return field * 25 / 100
}

and in you template helper-

Template.XXX.helpers({
    reusableHelper: function() {
        return calcField(this.field1); 
    },
    anotherHelper: function() {
        if (calcField(this.field1) > 300) 
            return calcField(this.field1) + ' is greater than 300'; 
        else
            return calcField(this.field1) + ' is smaller than 300';
    }
});

and

Alternatively is there a way to define reactive Template instance variables?

you can use Session variables or Reactive variable

like image 12
ajduke Avatar answered Oct 15 '22 01:10

ajduke


Disclaimer: This may not answer your question directly, but it might be helpful for people stuck with a similar use case:

Sometimes it's easy to get locked into the "Meteor way", that standard Javascript rules are forgotten.

Two use cases that sound similar to what you're trying to do:

1. For helpers/events that you can access anywhere on the client-side, simply set a global helper.

Put this in, say, client/helpers.js:

Helpers = {
    someFunction: function(params) {
        /* Do something here */
    }
}

Now Helpers.someFunction() is available to all templates.

If you want to bind the local template instance to it for some reason, again, it's standard JS:

var boundFunction = Helpers.someFunction.bind(this);

2. To create reusable Blaze helpers inside of templates, use Template.registerHelper

For example, this function uses the "numeral" library to format numbers:

Template.registerHelper('numeral', function(context, opt) {
    var format = (opt.hash && opt.hash.format) || '0,0.00';
    return numeral(context || 0).format(format);
});

You can use this in any template like so:

{{numeral someNumberVariable format='0,0'}}
like image 5
Lee Benson Avatar answered Oct 15 '22 01:10

Lee Benson