accessing data in template - meteor

When using {{#each}} in a template, I have to use {{this.name}} - {{this.thing}} instead of just {{name}} - {{thing}} for some reason.
{{thing}} prints out the proper value, but {{name}} is just a copy of {{thing}} instead of actually printing the correct value.
If I use {{this.name}}, the correct value is returned.
template.html
<template name="templ">
{{#each items}}
{{name}} - {{thing}}<br/> // name == thing unless i use this.name/this.thing
{{/each}}
</template>
template.js
Template.templ.helpers({
'items':function(){
return Items.find(); //also tried find().fetch()
}
});
EDIT console output of Items.find().fetch()
[Object, Object, Object, Object, Object]
0:{
Object_id: "er2KGErydGoZBwrMc",
name: "A",
thing: "b.txt"
},
1:{
Object_id: "vmkgkejA3TvLZu6c6",
name: "B",
thing: "b.txt"
},
2:{
Object_id: "jzA2szPiakXiLibCq",
name: "C",
thing: "c.txt"
},
3: {
Object_id: "RA29CJkgZHmhreWZo",
name: "E",
thing: "e.txt"
}
Using just {{name}} - {{thing}} in {{#each}} block renders value of thing for each item. {{this.name}} renders correct value for name.

Turns out I had a helper already named {{name}}. So {{#each}} {{name}}-{{thing}} {{/each}} was using the name helper instead of the data context.
oops

Related

How to set {{#each }} iterate value from helper

Usually for a {{#each}} block, we can set the value directly in it like: {{#each users}}:
user: [
{name: 'foo'},
{name: 'bar'}
]
What I need to do is do be able to set the {{#each}} iteration value from a helper.
I have tried with this helper:
Handlebars.registerHelper('myHelper', function () {
return new Handlebars.SafeString('users');
});
## also tested with:
Handlebars.registerHelper('myHelper', function () {
return 'users';
});
and in my view:
{{#each (myHelper)}} # and {{#each myHelper}}
<p>{{name}}</p>
{{/each}}
But nothing get shown.
I appreciate if anyone can give me some pointers. Thanks in advance!
You can use a built-in function called lookup in order to achieve what you are trying to achieve.
Try:
{{#each (lookup . (myHelper))}}
{{name}}
{{/each}}

Is there any way to nest 2 different object in handlebars with node js

I am trying to use each using handlebars for iterating over 2 objects of type array, when I iterate over them individually that works fine; but when there is a nesting of both inner object each isn't working.
a = [{a: "A"}, {a: "B"}, {a: "C"}]
b = [{b: "X"}, {b: "Y"}, {b: "Z"}]
Now these both objects can be iterated fine with
{{#each a}}
{{this.a}}
{{/each}}
{{#each b}}
{{this.b}}
{{/each}}
But it wont work for
{{#each a}}
{{this.a}} //this is getting printed
{{#each b}}
{{this.b}} //this isn't getting printed
{{/each}}
{{/each}}
(I've not mentioned any HTML syntax to reduce any confusions )
Your problem is that your data context is different when you are within the #each block. Within #each, your context is the current element in the iteration, { a: "A" }, { b: "B" }, etc. To access an object of the parent context you use Handlebars Paths:
{{#each a}}
{{this.a}}
{{#each ../b}}
{{this.b}}
{{/each}}
{{/each}}

Meteor: Spacebars each parameter

I'm new to Meteor.js and have run into a problem.
I am passing in a user object to a profile template e.g.:
{
_id: "D8JpXRQskm3grykjg",
username: "foo",
profile: {communities: ["AkGCakz6mSgMb8qyS", "j8aB3i5iscrC4ehkA"]},
}
<template name="profile">
<h1> {{username}}: {{_id}} </h1>
<h3>Communities</h3>
<hr>
{{#each profile.communities}}
{{> communityItem}}
{{/each}}
</template>
The problem is I've already written a communityItem template that I am using elsewhere which accepts the communityName. Is there a way that I can write a helper function, passing in the communityIds list that would return a list of community names? I would like:
...
{{#each getCommunityNames(profile.communities)}}
{{> communityItem}}
{{/each}}
...
I could very well be approaching the problem the wrong way or not writing in a "Spacebars" fashion. Thanks!
sure you can:
Template.myTemplate.helpers({
getCommunityNames: function(commIds) {
var communities = Communities.find({_id: {$in: commIds}}).fetch();
return _.pluck(communities, 'name'); // returns ['Name 1', 'Name 2'];
}
});
Note, the syntax method param not method(param)
{{#each getCommunityNames profile.communities}}
{{>communityItem}}
{{/each}}

'this' context in Meteor event is empty object

Template works fine (in terms of data being displayed), but event doesn't. Particularly odd because I have a different template with almost the identical code in which it works.
<template name="profile_sidebar">
{{#if opened}}
{{> profile_sidebar_contents}}
{{/if}}
</template>
<template name="profile_sidebar_contents">
{{#if dataReady}}
{{#unless equalsCurrentUsername profile.login}}
<span>
<a class="message-user"><i class="ion-chatbox"></i> Message</a>
</span>
{{/unless}}
{{/if}}
</template>
Template.profile_sidebar_contents.events({
'click .message-user': function(e,t){
// this is {}
// t.data is null
Session.set('selectedConversation', this._id);
Router.go('/messages');
}
});
Thank you!
Found a solution!
I wrapped the entire template in a {{#with profile}} ... {{/with}} block and then added the data I needed to be within the profile object returned in the helper. It seems as though the context of the event was empty object because the event target was not within a scope.
Elaborated below
I assumed that the context would default to an object which had as fields all helpers. Ex. I had
Template.profile_sidebar_contents.helpers({
profile: function(){ return something },
id: function() {return somethingelse }
});
and I expected the context of this to be {profile: something, id: somethingelse}
but it seems that this isn't done and the context is empty. I moved it to be
Template.profile_sidebar_contents.helpers({
profile: function(){ return {profile:something, id:somethingelse} }
});
and then set {{#with profile}} ... {{/with}} and had access to the profile helper returned object, by which I could retrieve id by this.id and profile by this.profile

Handlebars dynamic property lookup in each loop

In Handlebars 2+, how do I dynamically read a property in a loop like this? objects is an array of objects. keys is an array of strings. I want to loop each key for each object and put the its .foo value in the span.
{{#each objects}}
{{#each keys}}
<span>{{../this.{{this}}.foo}}</span>
{{/each}}
{{/each}}
Is this possible in plain Handlebars 2+? Or...is there a helper that does this?
I don't see the way how it can be done without helper.
With helpers everything is possible (but kind of ugly) in Handlebars.
For example, you could use something like this:
{{#each objects}}
{{#each keys}}
<span>{{lookupProp ../this this 'foo'}}</span>
{{/each}}
{{/each}}
And helper:
Handlebars.registerHelper('lookupProp', function (obj, key, prop) {
return obj[key] && obj[key][prop];
});
Look at the fiddle.
Handlebars has built-in lookup helper since version 3.0.3.
Okay... spent a few hours googling around and find a nice solution, as I had the same issue, but failed to find any...
I was as happy as Larry and jumped off my chair when I finally figured a way to get this working :D
This way, you can access object values with dynamic keys,
Demo object:
var categories = {
onion: { name: 'bar', id: 4 },
apple: { name: 'demo', id: 2 },
carrot: { name: 'foo', id: 3 },
Root: [
{ name: 'apple' },
{ name: 'onion' },
{ name: 'carrot' }
]
};
Instead of trying something like these: (which won't work)
{{#each categories.[#key]}}
or
{{#each categories.[mykey]}}
You can do:
{{#each categories.[Root] as |main-category|}}
{{#each (lookup ../categories main-category.name) as |sub-category|}}
{{sub-category.name}}
{{/each}}
{{/each}}
Hope it will help for someone else too :)
For anyone else that doesn't want to loop you could use with eg.
{{#with (lookup myObject myKeyVar) as |subObject|}}
{{subObject.key}}
{{/with}}

Resources