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!
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 :)
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
});
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.
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.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With