In my Handlebars template I check for the existence of a variable, and render some text if it's there:
{{#if foo}}
some text
{{/if}}
This works fine if foo is text or if foo is numeric but not zero. But if
var foo = 0;
then {{#if foo}} returns false.
This appears to be yet another Javascript oddity, because Javascript itself behaves the same way. In Javascript code, though, you could get around this by checking if the variable is 'undefined'.
How can I do the same thing in Handlebars?
I could write an {{#exists}} helper, but I was hoping there was something built in.
There is something built in for this:
{{#if foo includeZero=true}}
foo!
{{/if}}
This displays foo! when foo is 0.
I would go one better and provide a case for the {{else}} condition...
/**
* The {{#exists}} helper checks if a variable is defined.
*/
Handlebars.registerHelper('exists', function(variable, options) {
if (typeof variable !== 'undefined') {
return options.fn(this);
} else {
return options.inverse(this);
}
});
Now you can have:
{{#exists myvar}}
<p>Value of myvar is ... {{myvar}}</p>
{{else}}
<p>Please supply a myvar</p>
{{/exists}}
I just went ahead and wrote an {{#exists}} helper. But if someone has a better solution, please post it.
/**
* The {{#exists}} helper checks if a variable is defined.
*/
Handlebars.registerHelper('exists', function(variable, options) {
if (typeof variable !== 'undefined') {
return options.fn(this);
}
});
If anyone gets this error "Expecting 'ID', 'DATA', got 'SEP'" using #Shane method make sure you have no spaces in:
{{ /exist }}
And change it to this:
{{/exist}}
Related
i want to refresh/reload a part of my template after a variable change so that if the variable is true it shows a content A or else it will show content B. I'm sure this is a quite simple question but i'm having troubles on finding the solution.
Something like this:
Template.x.created = function() {
this.variable = false;
}
Template.x.helpers({
'getValue': function(){
return this.variable;
}
});
Template:
<template name="x">
{{#if getValue}}
<content A>
{{else}}
<content B>
{{/if}}
</template>
You need to create a reactive data source to get the template helper to re-run when the variable changes, as a normal variable won't let the helper know when it changes value. The simplest solution is to use ReactiveVar:
Template.x.onCreated(function() {
this.variable = new ReactiveVar(false);
});
Template.x.helpers({
'getValue': function() {
// Note that 'this' inside a template helper may not refer to the template instance
return Template.instance().variable.get();
}
});
If you need to access the value somewhere outside this template, you can use Session as an alternative reactive data source.
#Waiski answer is a good one, but I want to share a simple Template helper I build because a lot of Templates need this:
Using registerHelper you can build a global helper like so:
Template.registerHelper('get', function (key) {
let obj = Template.instance()[key]
return (obj && obj.get) ? obj.get() : obj
})
Use it in every template:
Template.x.onCreated(function() {
this.foo = new ReactiveVar(true)
this.bar = new ReactiveVar('abc')
})
Html:
{{#let foo=(get 'foo')}}
{{#if get 'bar'}}
Bar is true. Foo: {{foo}}
{{/if}}
{{/let}}
I have collection that has a document object "wageringStraightSpread" that sometimes is an embedded array. I need to check then look through the array, but i am not sure of the syntax of the {{if}} statement. I am specifically looking for help with this line {{#if team.[0].wageringStats.wageringStraightSpread = array}}. Thank you!
Here's what I got:
{{#if team.[0].wageringStats.wageringStraightSpread = array}}
{{#each}}
{{team.[0].wageringStats.wageringStraightSpread.this.line}}
({{team.[0].wageringStats.wageringStraightSpread.this.money}})
{{/each}}
{{else}}
{{team.[0].wageringStats.wageringStraightSpread.line}}
({{team.[0].wageringStats.wageringStraightSpread.money}})
{{/if}}
You can create a isArray helper that does the check:
Template.layout.helpers({
isArray: function(a){
return Array.isArray(a);
}
});
And use it from your html with:
{{#if isArray someVariable}}
First of all, your if condition is wrong. it is supposed to ==, not =. However, that is not the case, because if of Meteor template does not support boolean operation. Therefore, you will have to have a helper for this
Template.layout.helpers({
checkArray: function() {
// return the result of the comparison of
// team.[0].wageringStats.wageringStraightSpread == array.
// you do need to find the way to compare the array since == is also wrong
// for comparing the array
}
});
{{#if checkArray}}
{{/if}}
I am looping through documents in a template with Blaze spacebars to create a list
<template name="objectTemplate">
{{#if checkIfObjectExists}}
({{document.[0].object.object1}})
{{/if}}
</template>
I know that in some documents, some objects do not exist in that object position. normally if I didnt have (), it would be blank and I could move on, but in this case when empty, I will have a lot of () which is not good.
I created a helper, but its not working. I have tried null, 0, typeOf etc and still cant get it right. Anyhow here is the helper
Template.objectTemplate.helper ({
checkIfObjectExists: function() {
if (this !== 'null') {
return true;
} else {
return false;
}
}
});`
You can use _.has(object, key) if you want to check if the object document.[0].object has the property object1 set. The function _.isObject(value) will check instead if document.[0].object.object1 is an Object (this also includes arrays).
So, depending on your requirements, your template helpers should look like this:
Template.objectTemplate.helper({
checkIfObjectPropertyExists: function() {
return _.has(this.document[0].object, "object1");
},
checkIfPropertyIsObject: function() {
return _.isObject(this.document.[0].object.object1);
}
});
You could also register an Underscore.js global template helper and then use it directly in your Meteor templates:
Template.registerHelper('_', function () {
return _;
});
<template name="objectTemplate">
{{#if _.has this.document.[0].object 'object1'}}
({{document.[0].object.object1}})
{{/if}}
</template>
Your if is not in the right place. Your objectTemplate is probably called that way :
{{#each datum in data}}
{{>objectTemplate data=data}}
{{/each}}
So it's always rendered. Even if the datum is empty. The this you check in your helper will always be true, it's the template himself.
So, you should call it that way :
{{#each datum in data}}
{{#if datum.thingToTest}}
{{>objectTemplate datum=datum}}
{{/if}}
{{/each}}
The entire sub template won't be called.
I have the following helper
Template.meetingRow.helpers({
isOwner: () => {
console.log(this);
return Meteor.userId() === this.owner;
}
});
which will log the Window object to the console.
The this object returns the correct object in Template.meetingRow.events, and uses the correct values in the template, but isn't correct in the helper. Am I misunderstanding something?
Here's how it's being instantiated in its parent template:
<ul class="list-group">
{{#each meetings}}
{{ > meetingRow }}
{{/each}}
</ul>
It's because in ES2015, arrow functions inherit the context of the surrounding function, rather than being given their own. What this means is that Meteor can't bind a context to your helper function if it's defined this way.
Solution (in ES2015 style):
Template.meetingRow.helpers({
isOwner() function {
console.log(this);
return Meteor.userId() === this.owner;
}
});
More here under "Lexical this".
I'm definitely missing something about the way Handlebars works. I need to call different partials depending on the value of a variable. Currently the only way I've found to do it is this:
<template name="base">
{{#if a}}{{> a}}{{/if}}
{{#if b}}{{> b}}{{/if}}
{{#if c}}{{> c}}{{/if}}
</template>
And in the corresponding JS:
Template.base.a = function () {
return (mode === "a");
}
Template.base.b = function () {
return (mode === "b");
}
Template.base.c = function () {
return (mode === "c");
}
...which strikes me as extremely verbose. What I'd really like to do is something like:
<template name="base">
{{> {{mode}} }}
</template>
In other words, the value of mode would be the name of the partial that is called.
This seems like it must be a very common use-case, but I can't find any examples of this online. Where have I gone wrong?
The partials are stored in Handlebars.partials so you can access them by hand in your own helper. There are a few tricky bits here though:
The contents of Handlebars.partials can be strings or functions so you have to compile the partials on first use.
Handlebars doesn't know if the partial will be text/plain or text/html so you'll need to call your helper in {{{...}}} or {{...}} as appropriate.
This stuff isn't exactly documented (at least not anywhere that I can find) so you have to reverse engineer the Handlebars source and fumble about with console.log(arguments) to figure out how to use Handlebars.partials.
You have to pass this by hand when you call the helper.
Fear not, it isn't really that complicated. Something simple like this:
Handlebars.registerHelper('partial', function(name, ctx, hash) {
var ps = Handlebars.partials;
if(typeof ps[name] !== 'function')
ps[name] = Handlebars.compile(ps[name]);
return ps[name](ctx, hash);
});
should do the trick. Then you can say:
{{{partial mode this}}}
and get on with more interesting things.
Demo: http://jsfiddle.net/ambiguous/YwNJ3/2/
Update for 2016: Version 3 of handlebars added Dynamic Partials. From the docs:
It's possible to dynamically select the partial to be executed by using sub expression syntax.
{{> (whichPartial) }}
Will evaluate whichPartial and then render the partial whose name is returned by this function.
Subexpressions do not resolve variables, so whichPartial must be a function. If a simple variable has the partial name, it's possible to resolve it via the lookup helper.
{{> (lookup . 'myVariable') }}