Access an object's property names in a Blaze template - javascript

Say I have a helper that looks like this:
Template.profile.helpers({
info: {
Name: 'Bob Dinkleberg',
Age: 45,
Location: 'Earth, Milky Way'
}
});
I want to put this info in a <ul>. Here is some pseudo-code:
<template name="profile>
<ul>
{{#each}}
<li> {{key}}: {{property}} </li>
{{/each}}
</ul>
</template>
Forgive me if this is trivial, I am new to Meteor and Blaze, and I haven't been able to find a solution online.

If you want to loop through an objects properties and values as you requested, you can do it generic by:
Template.content.onCreated(function() {
this.properties = new ReactiveVar({
Name: 'Bob Dinkleberg',
Age: 45,
Location: 'Earth, Milky Way'
});
});
Template.content.helpers({
keys: function () {
return Object.keys(Template.instance().properties.get());
},
key_value_pair: function() {
return { key: this, value: Template.instance().properties.get()[this] };
}
});
and with this template
<body>
<h1>Property Loop</h1>
<ul>
{{> content}}
</ul>
</body>
<template name="content">
{{#each keys}}
{{> property key_value_pair }}
{{/each}}
</template>
<template name="property">
<li>{{key}}: {{value}}</li>
</template>
I prepared this MeteorPad for you which is a running example:
http://meteorpad.com/pad/24MGwbuMNCcXCC7EW/PropertyLoop
Cheers,
Tom
P.S.: It is not necessary to create the object as a ReactiveVar if there a never changes to its values. But by doing it as a ReactiveVar the form is als reactivly updated, when object content will change.

This will be helpful:
http://meteorcapture.com/spacebars/
You want to use {{#with}}.
<template name="profile">
<ul>
{{#with info}}
<li>{{Name}}</li>
<li>{{Age}}</li>
<li>{{Location}}</li>
{{/with}}
</ul>
</template>
While your helper code is correct:
Template.profile.helpers({
info: {
Name: 'Bob Dinkleberg',
Age: 45,
Location: 'Earth, Milky Way'
}
});
I personally like to make a habit of mapping the name of the helper to a function that returns something.
Template.profile.helpers({
info: function(){
return {
Name: 'Bob Dinkleberg',
Age: 45,
Location: 'Earth, Milky Way'
};
}
});
EDIT
Template.content.helpers({
info: function(){
var obj = {
Name: 'Bob Dinkleberg',
Age: 45,
Location: 'Earth, Milky Way'
};
var arrayOfObjects = [];
// creating an array of objects
for (key in obj){
arrayOfObjects.push({key: key, value: obj[key]});
};
console.log("This is the array of objects: ", arrayOfObjects);
return arrayOfObjects;
},
});
HTML:
{{#each info}}
{{value}}
{{/each}}

Related

Meteor dynamic category list

I would like to do the following. I would like to create a categories page that loads each category onto a picture. Then when a user clicks a category the parameter would show up on the url and it will search the database for photos based on that category. I will now demonstrate the code that I have.
Categories HTML File:
<template name="categories">
<div class="text-center light-container" id="categories-section">
<h1>Categories</h1>
<hr/>
{{#each categories}}
<div class="image-container">
<a href="{{pathFor route='categoryPage'}}">
<img class="freezeframe pics" src="images/app/sphere.jpg"/>
</a>
<h2><span>{{categories}}</span></h2>
</div>
{{/each}}
</div>
</template>
Categories JS File:
var categoryList = ['actions', 'animals', 'anime', 'art/design', 'cartoons/comics', 'celebrities',
'Emotions', 'Food/Drink', 'Games', 'History', 'Holidays', 'Memes', 'Movies', 'Music', 'Nature', 'News/Politics',
'Science', 'Sports', 'Technology', 'TV'];
Template.categories.helpers({
'categories':function(){
for(var i = 0; i < categoryList.length; i++){
console.log(categoryList[i]);
return categoryList[i];
}
}
});
Router JS File:
Router.route('/categories', {
name: 'categories',
template: 'categories',
fastRender: true
});
Router.route('/categories/:category', {
name: 'categoryPage',
template: 'categoryPage',
data: function(){
var category = this.params.category;
return GifsCollection.find({category: category});
},
fastRender: true
});
CategoryPage JS:
Template.categoryPage.helpers({
// Load 16 most recent ones
// When down arrow is click load another 16 more gifs
gifs: function() {
var category = this.params.category;
return GifsCollection.find({category: category}, {fields: {_id: 1, image: 1} });
}
});
Running the following code doesn't get me anywhere. I'm not sure which path to take. I can create a 'category' collection and load the helpers onto there or I can use sessions? but I'm leaning onto creating category collection however I'm pretty sure there is a much more efficient way.
Any feedback and code help would be greatly appreciated!!!
You have two small errors. One we already discussed in comments, regarding the helper. The other is in how you use the #each loop: inside of it you can just refer to this to get the string of your category.
Categories HTML File:
<template name="categories">
<div class="text-center light-container" id="categories-section">
<h1>Categories</h1>
<hr/>
{{#each categories}}
<div class="image-container">
<a href="/categories/{{this}}">
<img class="freezeframe pics" src="images/app/sphere.jpg"/>
</a>
<h2><span>{{this}}</span></h2>
</div>
{{/each}}
</div>
</template>
Categories JS File:
var categoryList = ['actions', 'animals', 'anime', 'art/design', 'cartoons/comics', 'celebrities',
'Emotions', 'Food/Drink', 'Games', 'History', 'Holidays', 'Memes', 'Movies', 'Music', 'Nature', 'News/Politics',
'Science', 'Sports', 'Technology', 'TV'];
Template.categories.helpers({
'categories':function(){
return categoryList;
}
});

Update Variable in Mustache Ractive Template

I am trying to get Ractive templates to go through a loop and compare the last accessed value to the current value.
My attempt at this was to create a helper function that updates a "lastValue" variable with the value the template loop has encountered.
You can see my jsfiddle here:
http://jsfiddle.net/k6hj6q46/3/
<script id='template' type='text/ractive'>
<ul>
{{#each names}}
<li>value: {{lastValue}}</li>
<li>{{name}}</li>
{{update(name)}}
{{/each}}
</ul>
</script>
<div id='container'></div>
var ractive = new Ractive({
// The `el` option can be a node, an ID, or a CSS selector.
el: '#container',
// We could pass in a string, but for the sake of convenience
// we're passing the ID of the <script> tag above.
template: '#template',
// Here, we're passing in some initial data
data: {
lastValue: 'oldValue',
names: [{
name: 'value1'
}, {
name: 'value2'
}],
update: function (newValue) {
console.log(newValue);
this.lastValue = newValue;
}
}
});
What about:
{{#each names:i}}
<li>last value: {{names[i-1]}}
<li>current value: {{this}}
{{/each}}

Meteor pass a dynamic variable from template to helper

I'm working on a meteor project where I want to place an objects from the same collection in different divs depending on their properties. The easiest way to explain is probably to show a test case:
html
<template name="board">
{{#each rows}}
<div id="row-{{this}}" class="row">
{{#each columns}}
<div id="{{..}}-{{this}}" class="column column-{{this}} row-{{..}}- column">
{{>pins }}
</div>
{{/each}}
</div>
{{/each}}
</template>
<template name="pins">
{{#each pins}}
<div class = "pin" >{{this}}</div>
{{/each}}
</template>
js
Template.board.helpers({
rows: [
'top',
'middle',
'bottom'
],
columns: [
'left',
'center',
'right'
]
});
Template.pins.helpers({
pins:[
{name: 'test1', loaction: 'bottomcenter'},
{name: 'test2', loaction: 'topleft'},
{name: 'test3', loaction: 'bottommcenter'},
{name: 'test4', loaction: 'middleright'}
]
});
I'd like to place the pins in the correct div based on their location. Now I can of course manually write out every div in the html and a helper for each one (and will if there's no better solution), but I'm trying to figure out what the most efficient solution is.
I tried passing the location back to the helper function with the following code:
{{#each pins location="{{..}}{{this}}}}
and this
{{#each pins location="{{..}}{{this}}"}}
and running a function, But the tags after location= come through as {{..}}{{this}} instead of the values.
I also tried restructuring the data like this:
pins:{
bottomcenter: [{name: 'test1'}, {name: 'test3'}]
topleft:[{name: 'test2'}]
}
etc, and passing the parameter as a data context:
{{>pins {{..}}{{this}}}}
but that didn't seem to work either. Any help is appreciated!
your template should like:
<template name="pins">
{{#each pins}}
<div class = "pin" >{{this.name}} {{this.location}}</div>
{{/each}}
</template>
and the helper like this:
Template.pins.helpers({
pins: function() {
return [
{name: 'test1', loaction: 'bottomcenter'},
{name: 'test2', loaction: 'topleft'},
{name: 'test3', loaction: 'bottommcenter'},
{name: 'test4', loaction: 'middleright'}
]
}
});
I think I got it! The trick seems to be that you can't embed {{}} brackets in other {{}} brackets. So you use:
<template name="pins">
{{#each pins .. this}}
<div class="pin">
{{this.name}}
</div>
{{/each}}
</template>
.. and this get passed back to the helper function, and then you can search based on the results:
Template.pins.helpers({
pins: function(row,col){
var search = row+"-"+col;
var results = [];
var pinarr = [
{insert data here}
];
for(var i = 0; i < pinarr.length ; i++){
if(pinarr[i].location === search) {
results.push(pinarr[i]);
}
}
return results;
}
});
}

Ember.js hasMany as list of checkboxes

I have the following two models:
App.Child = DS.Model.extend({
name: DS.attr('string')
});
And:
App.Activity = DS.Model.extend({
children: DS.hasMany('child',{async:true}),
name: DS.attr('string')
});
I want to use checkboxes to choose between the existing children, for the hasMany relation.
For example, I have these three children:
App.Child.FIXTURES = [
{ id: 1, name: 'Brian' },
{ id: 2, name: 'Michael' },
{ id: 3, name: 'James' }
];
The user should be able to use checkboxes, while creating or editing an activity, for choosing which children, to add to the hasMany relation.
I've created a JSFiddle to illustrate my question: http://jsfiddle.net/Dd6Wh/. Click 'Create a new activity' to see what I'm trying to do.
Basically it's the same as Ember.Select [ ... ] multiple="true", but for checkboxes.
What's the correct approach for something like this with Ember.js?
You can use an itemController in your each view helper to manage the selection. In the code below I created one called ChildController:
App.ChildController = Ember.ObjectController.extend({
selected: function() {
var activity = this.get('content');
var children = this.get('parentController.children');
return children.contains(activity);
}.property(),
selectedChanged: function() {
var activity = this.get('content');
var children = this.get('parentController.children');
if (this.get('selected')) {
children.pushObject(activity);
} else {
children.removeObject(activity);
}
}.observes('selected')
});
With a itemController you can expose some properties and logics, without add it directlly to your models. In that case the selected computed property and the selectedChanged observer.
In your template, you can bind the selection using checkedBinding="selected". Because the itemController proxy each model, the selected property of the itemcontroller will be used, and the {{name}} binding, will lookup the name property of the model:
<script type="text/x-handlebars" data-template-name="activities/new">
<h1>Create a new activity</h1>
{{#each childList itemController="child"}}
<label>
{{view Ember.Checkbox checkedBinding="selected"}}
{{name}}
</label><br />
{{/each}}
{{view Ember.TextField valueBinding="name"}}
<button {{action create}}>Create</button>
</script>
The same aproach in edit template:
<script type="text/x-handlebars" data-template-name="activities/edit">
<h1>Edit an activity</h1>
{{#each childList itemController="child"}}
<label>
{{view Ember.Checkbox checkedBinding="selected"}}
{{name}}
</label><br />
{{/each}}
{{view Ember.TextField valueBinding="name"}}
<button {{action update}}>Update</button>
</script>
This is a fiddle with this working http://jsfiddle.net/marciojunior/8EjRk/
Component version
Template
<script type="text/x-handlebars" data-template-name="components/checkbox-select">
{{#each elements itemController="checkboxItem"}}
<label>
{{view Ember.Checkbox checkedBinding="selected"}}
{{label}}
</label><br />
{{/each}}
</script>
Javascript
App.CheckboxSelectComponent = Ember.Component.extend({
/* The property to be used as label */
labelPath: null,
/* The model */
model: null,
/* The has many property from the model */
propertyPath: null,
/* All possible elements, to be selected */
elements: null,
elementsOfProperty: function() {
return this.get('model.' + this.get('propertyPath'));
}.property()
});
App.CheckboxItemController = Ember.ObjectController.extend({
selected: function() {
var activity = this.get('content');
var children = this.get('parentController.elementsOfProperty');
return children.contains(activity);
}.property(),
label: function() {
return this.get('model.' + this.get('parentController.labelPath'));
}.property(),
selectedChanged: function() {
var activity = this.get('content');
var children = this.get('parentController.elementsOfProperty');
if (this.get('selected')) {
children.pushObject(activity);
} else {
children.removeObject(activity);
}
}.observes('selected')
});
Updated fiddle http://jsfiddle.net/mgLr8/14/
I hope it helps

scoping of an action helper within a handlebars #each loop

I've become confused about the scoping within an {{#each}} block.
If I have the handlebars script
<script type="text/x-handlebars">
{{#each vars}}
<button {{action foo}}> {{name}} </button>
{{/each}}
</script>
and I set my application controller as
App.ApplicationController = Ember.Controller.extend({
vars: Ember.ArrayController.create({
content: [
{ name: "Cow",
foo: function(){console.log("moo");}
},
{ name: "Cat",
foo: function(){console.log("meow");}
}
]
})
});
The script can see {{name}} just fine and puts it in as the title of the button as you'd expect, but action does not get bound to the foo functions defined within the array members.
Is there are way to do this that I'm missing, or do I need to refactor to make foo be defined directly within ApplicationController?
You can set up an event on ApplicationController and pass in the individual object and call the stored foo(). Inside of the {{#each vars}}...{{/each}} block you can use this to pass the actual object to the event handler.
JS:
App.ApplicationController = Ember.Controller.extend({
vars: Ember.ArrayController.create({
content: [
{ name: "Cow",
foo: function(){console.log("moo");}
},
{ name: "Cat",
foo: function(){console.log("meow");}
}
]
}),
doFoo: function(obj) {
obj.foo();
}
});
Handlebars:
{{#each vars}}
<button {{action doFoo this}}> {{name}} </button>
{{/each}}
JSBin example
Action in handlebars template not firing
This may be due to the root element, check this posting here for more information

Categories