Replacing Jade for ... in loop with Handlebars - handlebars.js

I need convert Jade select list which iterates over statuses and assigns a status to an account into Handlebars template. In Jade it looks like this:
select.form-control(name='status')
option(value='') -- choose --
for status in data.statuses
option(value='#{status._id}') #{status.name}
I tried to do this with #each like this
<select name="status" class="form-control">
<option value="">-- choose --</option>
{{#each statuses}}
<option value="{{this._id}}">{{this.name}}</option>
{{/each}}
</select>
but it doesn't work because it is not an array.
Is there a way to do this with Handlebars? Thank you.

You can see this example:
http://jsfiddle.net/bby5ynuw/
var source = $("#some-template").html();
var template = Handlebars.compile(source);
var data = {
statuses:[
{_id:1, name:'name1'},
{_id:2, name:'name2'}
],
statuses2:{
o1:{_id:1, name:'name1'},
o2:{_id:2, name:'name2'},
o3:{_id:3, name:'name3'}
}
};
$('body').append(template(data));
Both variants (array and object) are working correct with your template. May be you set statuses into handlebars incorrect?

Related

How to manupulate {{#each something}} in the view ,where "something" is comming from database

Actually I am new to meteor . I want to manupulate {{#each something}} in my view, without manipulating database. Is there something like i treat it like an array. actually its returning the list of elements.
<select name="field">
<option value="">Lists</option>
{{#each something}}
<option value="{{_id}}">{{name}}</option>
{{/each}}
</select>
JUST I WANT TO SHOW ALL THE ELEMENT within "options" except the LAST element.
Any Help would be appreciated .
if you want to show everything in "something" except the last thing, you can use #index in Blaze to detect when you're at the end. i'm using the each/in construct because i think it's easier to read.
<select name="field">
<option value="">Lists</option>
{{#each thing in something}}
{{#if showThing #index}}
<option value="{{thing._id}}">{{thing.name}}</option>
{{/if}}
{{/each}}
</select>
for the JS, i'm making assumptions about how you get your data, but the helpers would look something like this:
Template.Foo.helpers({
something() {
return Somethings.find({});
},
showThing(index) {
let somethingsCount = Somethings.find({}).count();
return (index != (somethingsCount - 1));
}
});

Meteor Dropdown #each over a collection

I've been around this all day and i can't figure why my each cycle is not working. I'm trying to create a dropdown with some countries.
Helper
Template.register.helpers({
countries: function(){
return Country.find({ });
},
});
View, template register
<select id="country-select">
<option disabled="disabled" selected="selected">Please Select</option>
{{#each countries}}
<option value={{ name }}>{{ name }}</option>
{{/each}}
</select>
I have records in the country collection
meteor:PRIMARY> db.country.find({ }).count() ->
4
The only options that the dropwdown displays is the placeholder.
I'm using mongol this is a country record
Try this...
<option disabled selected>Please select</option>
{{#each countries}}
<option>{{name}}</option>
{{/each}}
It works here
Try
return Country.find().fetch()
in the helper
Thanks
Hope it helps
"The solution that worked for me is by calling the 'material_select' function after the options data has been loaded.
Template.[name].rendered = function() { this.autorun(function() { var optionsCursor = OptionsList.find().count(); if(optionsCursor > 0){ $('select').material_select(); } }); };"
from https://github.com/Dogfalo/materialize/issues/1469

Set value of a select HTML element reactively with Meteor

I want to set the value of an HTML <select> element reactively, without changing the various options for the element. I have found a solution, but it in not elegant.
To test, create a barebones Meteor app with create meteor select and change the contents of the select.html and select.js files to the following:
select.html
<body>
{{> select}}
</body>
<template name="select">
<label for="select">{{category}}</label>
<select id="select">
<option value='' disabled selected style='display:none;'>Select...</option>
<option value="Animal">Animal</option>
<option value="Vegetable">Vegetable</option>
<option value="Mineral">Mineral</option>
</select>
</template>
select.js
if (Meteor.isClient) {
Session.set("category", "")
Session.set("label", "Category")
Template.select.onRendered(function () {
setSelectValue()
})
Template.select.helpers({
category: function () {
setSelectValue()
return Session.get("label")
}
});
function setSelectValue() {
var select = $("#select")[0]
if (select) {
select.value = Session.get("category")
}
}
}
Now launch your app. In the browser console, you can change the value of the category Session variable:
Session.set("category", "Animal")
However, the select element will not update until you change the label:
Session.set("label", "category") // was "Category'
Now the select element updates, and any subsequent change the category Session variable will also update the select element.
Session.set("category", "Vegetable") // Now the select element updates
Is it possible to achieve the same effect directly, without using this clumsy workaround?
Yes. You can do it as follows:
<select id="select">
<option value="Animal" {{animalSelected}}>Animal</option>
<option value="Vegetable" {{vegetableSelected}}>Vegetable</option>
<option value="Mineral" {{mineralSelected}}>Mineral</option>
</select>
And helpers that looks something like this:
Template.select.helpers({
animalSelected: function () {
return (someCondition === true) ? 'selected' : '';
},
vegetableSelected: function () {
return (someOtherCondition) ? 'selected' : '';
}
});
A better way might be something like this though:
<select id="select">
{{#each options}}
<option value="{{value}}" {{selected}}>{{label}}</option>
{{/each}}
</select>
And then you can use this in the helpers to decide what is selected and what isn't.
Another option is just using standard jQuery to change the select box. Something like this:
$('[name=options]').val( 3 );
Or this SO answer.
If you want the selection set dynamically I usually use a handlebar helper like this
Template.newtask.helpers({
filler: function(element){
return Session.get(element);
}
});
then in html
<select class="browser-default" id="selectedService" name="jobtype">
<option id="zero" value="{{filler 'type'}}">{{filler 'type'}}</option>

Handlebars how to get sibling value inside an object

ok so iv got an object which looks like this:
Magnetim.photos = {
facebook:{albums: {id:["id1","id2","id3","id4"] , albumName:["n1","n2","n3","n4"]}},
}
inside a handlebars template im doing this line of code:
<select id="albums-selection">
{{#each photos.facebook.albums.albumName}}
<option id="{{photos.facebook.albums.id}}" value="{{this}}">{{this}}</option>
{{/each}}
</select>
this outputs this result:
<option id="id1,id2,id3,id4" value="n1">n1</option>
<option id="id1,id2,id3,id4" value="n2">n2</option>
<option id="id1,id2,id3,id4" value="n4">n3</option>
<option id="id1,id2,id3,id4" value="n4">n4</option>
but what i'm trying to achieve is for every name set the id element to its own id, so it looks like this:
<option id="id1" value="n1">n1</option>
<option id="id2" value="n2">n2</option>
etc..
While you are in the {{#each}} statement handlebars provides you with #index variable to track the current item index. Knowing this, you should be able to get corresponding item from other array.
So first you need to step outside of your {{#each}}, this is done by using ../, which will move you one level up.
My initial aproach was simply to do something like this
{{../albumName.[#index]}}
But for some reason that didn't work out. So I wrote the helper to simply grab item from array by index you pass there:
Handlebars.registerHelper('getAlbumName', function(array, id) {
return array[id];
});
Now your handlebars template will look like this:
<script id="template">
<select id="albums-selection">
{{#each id}}
<option id="{{this}}" value="{{getAlbumName ../albumName #index}}">
{{getAlbumName ../albumName #index}}
</option>
{{/each}}
</select>
</script>
<div id="output"></div>
And here is the js:
var Magnetim = {};
Magnetim.photos = {
facebook: {
albums: {
id: ["id1", "id2", "id3", "id4"],
albumName: ["n1", "n2", "n3", "n4"]
}
}
};
var source = $("#template").html();
var template = Handlebars.compile(source);
Handlebars.registerHelper('getAlbumName', function(albums, id) {
return albums[id];
});
$("#output").html(template(Magnetim.photos.facebook.albums));
Final jsfiddle with everything in place

Preselecting option in Meteor

Trying to implement a popup that allows you to modify an existing database record. As part of this, I have a couple of select boxes that I need to prepopulate with existing selections. This seems harder to do that I first thought. Here's a snippet of what I have as my template
{{#with myExistingRecord}}
<select class="myselect">
{{#each hoursInTheDay}}
{{#if isSelectedHour}}
<option selected>{{this}}</option>
{{else}}
<option>{{this}}</option>
{{/if}}
{{/each}}
</select>
{{/with}}
The problem I run into is in the isSelectedHour template function, because this can't have two definitions (the first being the #each value and the second being the record object). I need to compare the value in the #each loop with the value in my record, and I can't think of an elegant way to do this. I could always set my record value as a Session variable, but that's hacky.
Is there a good, non-hacky way to do this?
I had the same problem, and to my surprise there is a good way to this. You do have access to the outer context in the templating section, and you can use that to pass this to a value to a helper function. I would rewrite your code as follows:
<template name="myTemplate">
{{#with myExistingRecord}}
<select class="myselect">
{{#each hoursInTheDay}}
<option {{selected ../recordHour}}>{{this}}</option>
{{/each}}
</select>
{{/with}}
</template>
And then have a helper function:
Template.myTemplate.selected = function(hour) {
if (hour == currentHour)
{ return "selected ";}
else
{ return "";}
};
Look here for details on how the ../ notation works.
In the end I decided to create a simple Handlebars helper to handle this. If anyone wants to do something similar, here's the helper code:
Handlebars.registerHelper('hourOptions', function(selectedHour) {
var html = '';
for (var hr = 0; hr < 24; hr++) {
if (hr === selectedHour)
html += '<option selected>' + hr + '</option>';
else
html += '<option>' + hr + '</option>';
}
return new Handlebars.SafeString(html);
});
And the template code becomes
{{#with myExistingRecord}}
<select class="myselect">
{{hourOptions mySelectedHour}}
</select>
{{/with}}

Resources