Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing functions between templates in Meteor

Tags:

meteor

What if I have two handlebar templates that want to check the return value of the same function? Is there a right way to do this? Obviously I could do this:

var say_foo = function() {
  alert('foo');
};

Template.foo.say_foo = say_foo;
Template.bar.say_foo = say_foo;

But is there some way to do this directly through the Template object? Since this is JavaScript I can assign a function to any property of any object, but I tried doing:

Template.say_foo = function() { alert('foo'); };

and of course the templates don't find this function.

Just curious about best practices and the like. Thanks!

like image 318
Samo Avatar asked Apr 19 '12 01:04

Samo


4 Answers

I think a better version would be (if you use Handlebars, which is the default) :

Template.registerHelper('my_helper', function() {
     // code
});

You can call this from any template using {{my_helper}} !

Hope it helps :)

like image 166
Gabriel Dehan Avatar answered Sep 27 '22 20:09

Gabriel Dehan


According to the Meteor documentation, the correct way would be to use UI namespace, which would bind to whatever template engine used underneath, instead of using Handlebars, or spacebars directly. Here is the link in documentation. http://docs.meteor.com/#ui_registerhelper

So for generic function to be accessed from any template use in client.js:

UI.registerHelper('stub', function() {
     // code
});

Update:

Apparently the docs have changed back to using:

Template.registerHelper('stub', function() {
     // code
});

Then in the the html file use {{stub}} to access the variable.

like image 27
srinivas Avatar answered Sep 27 '22 22:09

srinivas


Here's what I came up with to solve the problem. This is done using CoffeeScript. If you're not using CoffeeScript, you can convert it to JavaScript here.

First, define the extendTemplate function:

extendTemplate = (template, mixin) ->
  helpers = ({name, method} for name, method of mixin when name isnt "events")
  template[obj.name] = obj.method for obj in helpers

  if mixin.events?
    template.events?.call(template, mixin.events)

  template

Then, declare an object with helpers and events (mine is called loginMixin) that you'd like to share across multiple templates:

loginMixin =
  merge_with_email: ->
    return Session.get 'account_merge__merge_with_email'

  events:
    'click button#merge_login': (event, template) ->

      email = $(template.find('#email')).val()
      password = $(template.find('#password')).val()

      Meteor.loginWithPassword email, password, (error)->
        if error
          console.error "Failed to login."

      return false

Then, after declaring your templates, you can extend them with the above mixin. With the following code, I'm extending my register and login templates:

extendTemplate Template.register, loginMixin
extendTemplate Template.login, loginMixin

Lastly, here's how my login.html can look like:

<template name="login">
    <div class="alert">
        <a class="close" data-dismiss="alert" href="#">×</a>
        <h4 class="alert-heading">Merge accounts</h4>
        <form id="register_form" class="form-inline" action="#">
            <p class="help-block">Please login with {{merge_with_email}}.</p>
            <label for="email">Email:</label>
            <input id="email" type="text" class="input-medium" />
            <label for="password">Password:</label>
            <input id="password" type="password" class="input-medium" />
            <button class="btn" id="merge_login">Login</button>
        </form>
    </div>
</template>

Since I extended my register template as well, register.html can also use {{merge_with_email}} and have the click event of the merge_login button handled as well.

like image 39
Gezim Avatar answered Sep 27 '22 22:09

Gezim


With Meteor 1.0 here now, this seems to have changed. After some digging, I found that you can now use the following to reuse code between helpers:

https://docs.meteor.com/#/full/template_registerhelper

Template.registerHelper("checkedIf",function(value){
  return (value)? "checked":"";
});

This makes it available in all helpers!

like image 33
François Avatar answered Sep 27 '22 20:09

François