I've created a custom block helper for Meteor 0.9.3 using information from the following URL:
https://github.com/meteor/meteor/wiki/Using-Blaze#new-pattern-for-defining-custom-block-helpers
It can be used within a Spacebars template like so:
{{#ifEqual value1="stringOrNumber_1" value2="stringOrNumber_2"}}
<h1>The values ARE equal!</h1>
{{else}}
<h1>The values are NOT equal!</h1>
{{/ifEqual}}
Here is the code:
<template name="ifEqual">
{{#if isEqual value1 value2}}
{{> UI.contentBlock}}
{{else}}
{{> UI.elseBlock}}
{{/if}}
</template>
Template.ifEqual.isEqual = function (value1, value2) {
return value1 === value2;
};
My question is:
Is there a possible way to make this less clunky?
I would much prefer code that can be used within a template like so:
{{#ifEqual "stringOrNumber_1" "stringOrNumber_2"}}
...
I would register a global equals helper:
Template.registerHelper('equals', function(value1, value2){
return value1 === value2
})
And then use it like this:
{{#if equals "abc" "abc"}}
<p>They're equal :)</p>
{{else}}
<p>They're not equal :(</p>
{{/if}}
Though, you may be interested in using the underscore-helper package instead, so you don't have to define this (and similar) helpers yourself.
Related
How can I write an if not x statement in an HBS template file?
At present, I use an if/else clause in order to achieve that:
{{#if x}}
{{else}}
Some Text
{{/if}}
Is there a way to simplify this and use a single if statement?
I've tried stuff like {{#if !x}} and {{#if ^x}}, but it didn't work of course.
Looking on the web for HBS logical operators, I couldn't quite find the syntax for a logical-not.
Update
I should emphasize that in my case x is undefined.
I've learned it "the hard way", while trying:
{{#if not x}}
Some Text
{{/if}}
Which threw TypeError: Cannot read property 'includeZero' of undefined.
Have you tried unless?
<div class="entry">
{{#unless license}}
<h3 class="warning">WARNING: This entry does not have a license!</h3>
{{/unless}}
</div>
You can use the unless helper as the inverse of the if helper. Its
block will be rendered if the expression returns a falsy value.
https://handlebarsjs.com/builtin_helpers.html
You can also considers custom helpers:
Handlebars.registerHelper("ifNot", function(a, options){
if (!a) {
return options.fn(this);
}else{
try{
return options.inverse(this);
}catch(e){
//no else statement
}
}
});
Looking at this Using Blaze guide, it seems Blaze supports {{#if}} and {{else}} statements, but I have't seen examples of an if-else statement. Is this supported in Blaze? Or do I have to do an additional if block inside the else block, which can get ugly.
I tried {{else if}}, but that gave an error.
{{#if en}}{{text.en}}{{else if tc}}{{text.tc}}{{/if}}
Spacebars uses the same control flow structure as handlebars so the answer is the same as this one. In your case:
{{#if en}}
{{text.en}}
{{else}}
{{#if tc}}
{{text.tc}}
{{/if}}
{{/if}}
Side note - one of the nice things about jade is that it supports else if.
Sometimes a better alternative is to move the logic into a helper like this:
Template.myTemplate.helpers({
textValue: function() {
if (this.en) {
return this.text.tc;
} else if (this.tc) {
return this.text.tc;
}
}
});
<template name="myTemplate">
<p>{{textValue}}</p>
</template>
The current version of Blaze supports else if - see below for a sample format and reference to the github issue resolution.
{{#if isUserProfile}}
<h3>User Profile</h3>
{{else if isLawyerProfile}}
<h3>Lawyer Profile</h3>
{{else}}
<h3>Test</h3>
{{/if}}
Reference Link: GitHub Else If Issue Resoltion
Following on from #David Wheldon's excellent answer, it's also worth noting that you can pass parameters to your JavaScript helper functions from your Blaze template.
So, for example the code below selectively renders the options for a select list by calling the helper method with the line isSelected region customerCompany:
{{#if isSelected region customerCompany}}
<option value={{region._id}} selected>{{region.name}}</option>
{{else}}
<option value={{region._id}}>{{region.name}}</option>
{{/if}}
and then in the js file:
isSelected: function (region, customer) {
return customer.salesRegionId === region._id;
},
This approach of passing in your variables to your helpers is generally recommended to avoid the confusion that can the arise with the changing meaning of the this keyword when using templates.
I am trying to assign values within a template, the idea is to do something like this:
{{#if author}}
{{className = 'classA'}} <- trying to implement this line.
{{else}}
{{className = 'classB'}}
{{/if}}
<div class={{className}}></div>
Is it possible to do so without registerHelper?
I needed this solution solved in the same way the original poster expected. Therefore I created a helper function to do this for me.
function setVariable(varName, varValue, options){
options.data.root[varName] = varValue;
};
Contained within the options in the helper, is the data block, with the root of the helper variables.
I placed my variable within the root object, either assigning or overwriting with the value provided.
The helper in html looks a lot like this.
{{setVariable "thisVar" "Contents Here"}}
<div>
{{thisVar}}
</div>
You can do this with a partial.
partial:
<div class="{{classname}}">{{var1.author}}</div>
template:
{{#if author}}
{{> mypartial var1=. classname="classA"}}
{{else}}
{{> mypartial var1=. classname="classB"}}
{{/if}}
In this example I've passed the current scope as var1. I can't recall if the scope stays the same and the new variable is just added to it or if you have to pass the scope manually.
Small update from a helpful above answer. In Handlebars 4.x, it seems we have to get the variables from #root.
handlebars.registerHelper('assign', function (varName, varValue, options) {
if (!options.data.root) {
options.data.root = {};
}
options.data.root[varName] = varValue;
});
And then,
{{assign 'imageTag' 'drop-155'}}
{{#root.imageTag}}
{{#if author}}
<div class='{{ classA }}'></div>
{{else}}
<div class='{{ classB }}'></div>
{{/if}}
or try
<div class='{{#if author}} {{ classA }} {{else}} {{ classB }} {{/if}}'></div>
or maybe this
create a script
<script>
$(function(){
var class;
{{#if author}}
class = {{ classA }}
{{else}}
class = {{ classB }}
{{/if}}
var $specials = $('.special');
$specials.removeClass('special');
$specials.addClass(class);
})
</script>
Say we have a parent template and a child template:
<template name="parent">
{{> child }}
</template>
<template name="child">
{{#if show}}
//Do something
{{/if}}
</template>
If we assign 'show' to the parent template:
if (Meteor.isClient){
Template.parent.show = function(){
return Session.get('isShowing');
}
}
Is there any way for the child template to have access to it?
Edit
You could make a universal handlebars helper so you could use Sessions values anywhere in your html:
Client js
Handlebars.registerHelper('session', function(key) {
return Session.get(key);
});
Client HTML
<template name="child">
{{#if session "show"}}
//Do something
{{/if}}
</template>
Similarly, you could also use {{session "show"}} / {{#if session "show"}} in your parent template and not have to use the Template.parent.show helper anymore.
Regarding the use of ../ notation. There are certain scenarios it may not work: https://github.com/meteor/meteor/issues/563. Basically it works within {{#block helpers}} but not with templates, but it would work in a block helper if it contains a subtemplate.
<template name="child">
{{#if ../show}}
Do something
{{/if}}
</template>
You can also register a common helper :
Template.registerHelper('isTrue', function(boolean) {
return boolean == "true";
});
And call it just like that in your html:
<input type="checkbox" checked="{{isTrue attr}}"/>
I have started using Handlebars.js. It seems that there is no built in conditionals like else if.
I want to have something like this
{{#if type.one }}
do something ... IF
{{else if type.two}}
do something ... ELSE IF
{{else}}
do something ... ELSE
{{/if}}
But this doesn't work. How do I do ELSE IF with handlebars? Is writing a custom helper is the only option ? If yes then please provide some pointers to write this helper.
You can't do this with a custom helper as Handlebars if-ish helpers only understand two parts: the "if" part and the "else" part. You can nest things though:
{{#if type.one}}
do something ... IF
{{else}}
{{#if type.two}}
do something ... ELSE IF
{{else}}
{{#if type.three}}
...
{{else}}
...
{{/if}}
{{/if}}
{{/if}}
That sort of thing will get nasty fast so you probably don't want to do that. A better approach would (as usual with Handlebars) be to push the logic into your JavaScript so that at most one of type.one, type.two, type.three, ... would be true; then you could:
{{#if type.one}}
...
{{/if}}
{{#if type.two}}
...
{{/if}}
{{#if type.three}}
...
{{/if}}
If you have a lot of options for type or if the bodies in your {{#if}}s are complicated, you could switch to partials. You'd have to add a custom helper to build a partial name based on a template variable though; something like this:
Handlebars.registerHelper('show_type', function(type) {
var types = ['one', 'two', 'three'];
var partial;
for(var i = 0; i < types.length; ++i) {
if(!type[types[i]])
continue;
partial = '_partial_' + types[i];
break;
}
if(partial)
return Handlebars.partials[name](this);
else
return '';
});
and then, assuming your partials are all registered and consistently named, you could say:
{{show_type type}}
Since Handlebars 3.0 the syntax described by OP does work out of the box! See: https://github.com/wycats/handlebars.js/pull/892 for more information.
Note:
For Ember, since version 1.10 and up this does work too. See also:
http://emberjs.com/blog/2015/02/07/ember-1-10-0-released.html#toc_chained-else-blocks
if you are using ember like framework,
{{#if isAtWork}}
Ship that code!
{{else if isReading}}
You can finish War and Peace eventually...
{{/if}}
link : http://guides.emberjs.com/v1.12.0/templates/conditionals/
You can do this:
{{#if type.one}}
...
{{else}} {{#if type.two}}
...
{{else}} {{#if type.three}}
...
{{else}}
...
{{/if}}{{/if}}{{/if}}
If you want a switch behaviour, you might be interested in Dan Harper's helpers, you will be able to do something like :
{{#is type 1}}
<p>Do something when 1.</p>
{{else}}{{#is type 2}}
<p>Do something when 2.</p>
{{else}}{{#is type 3}}
<p>Do something when 3.</p>
{{/is}}{{/is}}{{/is}}
Here is the jsfiddle.
The exact syntax that the OP has written will work in Ember Canary today with the
ember-htmlbars-inline-if-helper feature flag enabled.