How to use equals == operator in if else condition in handlebar - node.js

Below is the code i want check:
{{#each user.Addtasks}}
{{#if {{this._id}} == {{ID}} }}
Statement;
Statement;
{{/if}}
{{/each}}
Here _id and ID both are getting passed from route to the handlebar page and now I want to compare them.
Thanks!

Related

Jsviews filter search

How do I create a filter search in JSViews? Usually I'd grab the html element by its class with the .getElementsByClassName() and .value() methods and add a === comparison to satisfy the right criteria. How can I do something similar in JsViews
I've already tried to add listItem in the IF to match the value of the html input (search bar), but I don't know how to grab the value of the search element (JQuery would be easy using $(".search")), or compare it to the listItems using regExp.
{^{if list && list.length}}
<ul autoselectitem="true" tabindex="-1" operationalindex="1" allindex="1">
{^{for list}}
{{include tmpl="listItem" /}}
{{/for}}
</ul>
{{else}}
<p>Nothing Found</p>
{{/if}}
This currently displays all items in the list, however I only want the elements in the list to be displayed that match with RegEx the .value of an search HTML element:
<input type="text" class="search" data-link="search" placeholder="Search...">
So for example, if I type in "e" into the search bar, all the items in the list that don't have the letter "e" should disappear.
The code linked all work, but what i've tried has given me null pointer errors because I'm not grabing the input element correctly by its class or data-link. How could I do this in the simplest way possible? Thanks
Here is one way of doing it:
<script id="myTmpl" type="text/x-jsrender">
<input type="text" class="search" data-link="search" placeholder="Search...">
{^{if list && list.length}}
<ul autoselectitem="true" tabindex="-1" operationalindex="1" allindex="1">
{^{for list filter=~flt depends="search"}}
<li data-link="#data"></li>
{{/for}}
</ul>
{{/if}}
</script>
<div id="page"></div>
<script>
var myTmpl = $.templates("#myTmpl"),
data = {
list: ["a", "b"],
search: ""
},
helpers = {
flt: function(item, index, items) {
return item.indexOf(data.search) > -1;
}};
myTmpl.link("#page", data, helpers);
</script>

Access to next array item in handlebars.js

I need access to next item in array while using foreach loop in handlebars.js.I've tried:
{{#each items}}
{{#ifEven #index}}
<p>{{this.description}} - {{../items.[#index+1].description}}</p>
{{/ifEven}}
{{/each}}
but it seems that's not working correctly.
I already solved it using helper:
hbs.registerHelper('nextItem', function (array, index, options) {
return options.fn(array[index + 1]);
});
And .hbs template now looks like this:
{{#each items}}
{{#ifEven #index}}
<p>{{this.description}} - {{#nextItem ../items index}} {{description}} {{/nextItem}}</p>
{{/ifEven}}
{{/each}}
I know, that last element will not show, but this doesn't matter in my case.

Compare iteration values using handlebars

I want to compare iteration values using handlebars. This is my code
{{#each accounts}}
{{#each projects}}
{{#if}} (compare accounts.project_id with projects._id)
// display the project name
{{else}}
// display not found
{{/if}}
{{/each}}
{{/each}}
Please help. I'm new to handlebars/
Use the {{compare}} helper from the handlebars-helpers module.
{{#each accounts}}
{{#each projects}}
{{#compare accounts.project_id "==" projects._id)
// display the project name
{{else}}
// display not found
{{/compare}}
{{/each}}
{{/each}}
Refer to the documentation on how to install and use the helpers.
You can do so with a simple helpers in Handlebars like so:
Handlebars.registerHelper('if_eq', function(a, b, opts) {
if(a == b)
return opts.fn(this);
else
return opts.inverse(this);
});
and in your code...
{{#each accounts}}
{{#each projects}}
{{#if_eq accounts.project_id projects._id}}
// display the project name
{{else}}
// display not found
{{/if_eq}}
{{/each}}
{{/each}}

How to check type of object in Handlebars?

I am currently working on a search bar that lists three types of objects: users, records and locations. Each has its own model and such defined, with corresponding controllers. What I need to do is to check which type of object it is because I need the HTML that renders with it to be different.
{{#each mainUserSearchResults}}
{{#link-to 'user' this.userID}}
<div class="row mainListSeperator" {{action "getapplicantUserID" this target="view"}}>
<img class="applicantsIcon" src="">
<div class="applicantsName">
{{unbound this.firstName}} {{unbound this.lastName}}
</div>
<div class="applicantsTitle">
User
</div>
</div>
{{/link-to}}
{{/each}}
The only issue I am having is that I need it to print this.firstName & this.lastName if it is a user, but I cannot do that for records. For records, I would have to render another property - this.recordID - in the same manner as I did this.firstName. The way to do this would be an if conditional, but I cannot find anything in HandleBars that allows me to check whether the data coming in from mainUserSearchResults is a user or a record.
The mainUserSearchResults is a property in my controller that returns an array of objects: currently it return a concatenated array of user objects and record objects.
Handlebars is a logicless template, so you really can't perform computations, like type-checking. There are some pretty good reasons for this. If it were me, I'd push that responsibility elsewhere, probably all the way to your model, for two reasons:
Any conditionals you put in the DOM are SLOW. The problem only gets compounded when you're on slow devices (most notably, mobile).
Every time you add a new searchable thing, you're going to have to update your templates. Over time, you'll end up with:
{{#if ...}}
...
{{/if}}
{{#if ...}}
...
{{/if}}
{{#if ...}}
...
{{/if}}
{{#if ...}}
...
{{/if}}
Delegate instead. For example, in your User model, add
formattedName: (function() {
return [this.get('firstName'), this.get('lastName')].join(' ');
}).property('firstName', 'lastName')
Do the same for your records and locations.
Then, change your template from
{{unbound this.firstName}} {{unbound this.lastName}}
to
{{unbound this.formattedName}}
Now, if you add new types to your searches, you have a completely generic solution that only needs the model to implement the formattedName property.
Some would would say my suggestion is a bad one, because it mixes the business-logic responsibility of a model with display logic. In this case, I'm guessing you're displaying {{firstName}} {{lastName}} in more than one place, so I think the benefits of keeping your code DRY outweigh moving this to, e.g., a controller. Your call.
Assuming there is some way to easily distinguish between the 2+ types of objects, you can use an if statement and render a different template (or even use a different partial, http://emberjs.com/guides/templates/rendering-with-helpers/)
<script type="text/x-handlebars" data-template-name="index">
<ul>
{{#each item in model}}
<li>
{{#if item.foo}}
{{render 'foo' item}}
{{/if}}
{{#if item.cow}}
{{render 'cow' item}}
{{/if}}
</li>
{{/each}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="foo">
I'm a foo: {{foo}}
</script>
<script type="text/x-handlebars" data-template-name="cow">
I'm a cow: {{cow}}
</script>
http://emberjs.jsbin.com/qinilege/1/edit
Or if you need more advanced checking you can use an item controller and add the logic in there
{{#each item in model itemController='checker'}}
<li>
{{#if item.isFooBar}}
{{render 'foo' item.model}}
{{/if}}
{{#if item.isFooBaz}}
{{render 'fooz' item.model}}
{{/if}}
{{#if item.isCow}}
{{render 'cow' item.model}}
{{/if}}
</li>
{{/each}}
App.CheckerController = Em.ObjectController.extend({
isFooBar: Ember.computed.equal('foo', 'bar'),
isCow: Ember.computed.notEmpty('cow'),
isFooBaz: Ember.computed.equal('foo', 'baz')
});
http://emberjs.jsbin.com/qinilege/2/edit

Strange results with nested handlebar blocks in Meteor

I am trying to set default value in an html select, but without sucess.
I'm doing the initial populating like this:
<template name="demo">
<select>
{{#each foo}}
<option>{{this}}</option>
{{/each}}
</select>
</template>
And i set the possible options in the model like this:
Template.demo.foo = ["aaa","bbb","ccc"];
So far, everything work as intended.
Now i'm trying to display row of the collection collec, populating the select with the defaut recorded foo value (aaa or bbb or ccc).
My understanding is that you must add "selected" to the tag.
So i do something like this with multiple nested blocks:
<template name="demo">
{{#each collecs}}
{{_id}}
<select>
{{#each foos}}
<option{{#if isSelected this ../this}}selected{{/if}}>{{this}}</option>
{{/each}}
</select>
{{/each}}
</template>
And on the model front:
Template.demo.foos = ["aaa","bbb","ccc"];
Template.demo.collecs = function(){
return Collec.find({});
};
Template.demo.isSelected = function(fooToCheck, record){
var rid= record._id;
var currentRecord = Collec.findOne({_id:rid});
return (fooToCheck==currentRecord.foo);
};
The problem is that it does not work.
The dropdown stays empty, and the generated html code show something like this:
" >aaa "
I have checked in the js part, all seems to work correctly, true/false are adequately returned.
Thank in advance for your help.
Handlebars conditionals don't do well inline. In fact, I'm not sure if they work inline anywhere. What was happening was that the Handlebars templating engine didn't understand your html, so it skipped over it, which is why you saw '>aaa'.
The following code works. I took the liberty of simplifying your isSelected function.
Template:
<template name="demo">
{{#each collecs}}
{{_id}}
<select>
{{#each foos}}
{{#if isSelected this ../foo}}
<option selected>{{this}}</option>
{{else}}
<option>{{this}}</option>
{{/if}}
{{/each}}
</select>
{{/each}}
</template>
JavaScript:
Template.demo.foos = ["aaa","bbb","ccc"];
Template.demo.collecs = function(){
return Collec.find({});
};
Template.demo.isSelected = function(fooToCheck, recordFoo){
return (fooToCheck === recordFoo);
};

Resources