Meteor + Blaze - If else statement - meteor

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.

Related

Using an "if not x" statement in an HBS template file

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
}
}
});

how to know 'each' done or re done in meteor blaze template

each running after onRendered and Tracker.autorun(if foo is binding subscription data context).
so i cant catch thateach` work is when done.
how to know each is work done, or rework and done?
is it unknown?
Below is an example.
<template name="something">
{{#each foo}}
<bar>bar</bar>
{{/each}}
</template>
I don't see a real use case for this but you can use a helper here that does not add anything to the render output:
<template name="something">
{{#each foo}}
<bar>bar</bar>
{{isDone #index foo}}
{{/each}}
</template>
Template.something.helpers({
isDone(index, arr) {
if (index === arr.length - 1) {
// this was the last element
// to be rendered. do whatever
// you want here
}
}
})
Not that this is not really a best practice and you should think about why you need to know this? If you have performance issues with your rendering you want review your whole template code design and refactor where necessary.

With clause changes keypath

I have the following template:
{{#each Posts}}
{{#with { Post: this } }}
<h2 on-click="doSomething">{{Title}}</h2>
...
{{/with}}
{{/each}}
When I click on the header and doSomething get called, I get "${{Post:Posts-0}}" in event keypath. But I need to get access to the post keypath: "Posts.0" to modify some of its properties. What is the right way to achieve that?
Using a {{#with { a: b } }} block for aliasing in Ractive has some limitations, as it's not true aliasing, it's simply creating an expression with an object literal. It's a needed enhancement to offer true aliasing with something like {{#each Post in Posts}} or {{#each Posts as Post}}.
As far as what you can do today, you can add the keypath to the with block:
{{#with { Post: this, keypath: #keypath } }}
And then either pass in:
<h2 on-click="doSomething:{{keypath}}">{{Title}}</h2>
Or access in the event via this.event.context.keypath. See http://jsfiddle.net/w0npbnrz/ for both of these in action.
You also could use {{#each Posts:p}} in which case you could get the keypath via 'Posts.' + this.event.index.p.

how to insert a string containing a link with a helper in meteor blaze

I would like to insert a string that contains a link with a helper (or is there any better option to achieve this?) in meteor blaze.
So far blaze just gives back the link as normal text with the '' tags.
Does anyone have a good solution or workaround for this?
Here is a simple example to get you started :
<template name="parent">
{{> linkTemplate linkData}}
{{#each links}}
{{> linkTemplate}}
{{/each}}
</template>
<template name="linkTemplate">
{{title}}
</template>
Links=new Meteor.Collection(null);
Links.insert({
url:"https://www.google.com",
title:"Google"
});
Template.parent.helpers({
linkData:function(){
return {
url:"https://www.google.com",
title:"Google"
};
},
links:function(){
return Links.find();
}
});
If you want to render a string in a template that happens to contain a link, you would have to provide the HTML string as in
var string="A link to Google.";
Then you can use the triple bracket syntax {{{helperReturningHTMLString}}} and it will work as expected, but I don't think it's good practice unless you're working with something like a WYSIWYG editor.

handlebar js custom helper for else if

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.

Resources