Get nested key inside #each loop in Handlebars - handlebars.js

Imagine my data looks like this:
{
data: [
{ col1: 'Value1', col2: 'Value2', col3: 'Value3', col4: 'Value4' },
{ col1: 'String1', col2: 'String2', col3: 'Stringe3', col4: 'String4' }
...
],
query: ['col1', 'col3']
}
I want then to show with handlebars the data whose keys matches one of the items in query (here: I only want to show col1 and col3of each row of the data). How would I do that?
Here is what I tried:
{{#each data}}
<tr>
{{#each ../query}}
<td>{{../this[this]}}</td>
{{/each}}
</tr>
{{/each}}
But unfortunately it didn't work.

Try this
{{#each data}}
<tr>
{{#each ../query}}
<td>{{lookup ../this this}}</td>
{{/each}}
</tr>
{{/each}}

Related

how to output {{category}} where id = 234234

Using Node/Express + handlebars. I'm trying to output the category field where an _id = '234234'
I have a mongo db with this:
cms> db.categories.find()
[
{ _id: ObjectId("123123"), category: 'AA', __v: 0 },
{ _id: ObjectId("234234"), category: 'BB', __v: 0 }
]
I'm aiming to use {{ ??? }} in a .handlebars file (HTML) e.g. {{category}} but this outputs the _id, not the category text (AA or BB depending on _id).
In index.handlebars:
...
<tbody>
{{#each posts}}
<tr>
<td>{{title}}</td> <!-- title from posts db -->
<td>{{category}}</td> <!-- category from categories db, currently outputs _id-->
</tr>
{{/each}}
</tbody>
I guess I'm asking for something like psuedo-code:
SELECT categories.category where categories.id = '234234'
but in node/express javascript/handlebars

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):How to use #with and #each together

I have a helper function which is returning array of objects and each object of array has key publishers which is an object containing keys. Each key again has a object.
priceData:function(){
var colection=[
{contract:"nn",publishers:{GVM:{ask:1,bid:2},SET:{ask:6,bid:3}}},
{contract:"BB",publishers:{GVM:{ask:11,bid:99},SET:{ask:23,bid:34}}}
]
return colection
}
Now in template I am trying to use it like this
<table class="table">
<tbody>
{{#each priceData}}
<tr>
{{#with publishers}}
<td>{{ask}}</td>
<td>{{bid}}</td>
{{/with}}
</tr>
{{/each}}
</tbody>
</table>
Can I use #with in a #each iteration because it gives error like this. If not then how can I show such collection information in a table?Right now its empty table
There is no problem with each and with, you can combine them and nest at your will. The only thing to keep in mind is context: each of the blocks goes deeper into the context but at the same moment allows access outer contexts (which I personally wouldn't recommend). So if you remove all the typos and use the whole code in this way:
<table class="table">
<tbody>
{{#each priceData}}
<tr>
{{#with publishers}}
<td>{{ask}}</td>
<td>{{bid}}</td>
{{/with}}
</tr>
{{/each}}
</tbody>
</table>
then everything will be fine. But make sure the data structure corresponds with this code. But it doesn't.
What you need is to access ask and bid within publishers through either GVM or SET. Let's pretend you need the former:
<table class="table">
<tbody>
{{#each priceData}}
<tr>
{{#with publishers}}
<td>{{GVM.ask}}</td>
<td>{{GVM.bid}}</td>
{{/with}}
</tr>
{{/each}}
</tbody>
</table>
Let's deconstruct the whole code to make the picture clearer.
When you use
{{priceData}}
then you link to what the helper returns, i.e.
[{
contract: "nn",
publishers: {
GVM: {
ask: 1,
bid: 2
},
SET: {
ask: 6,
bid: 3
}
}
}, {
contract: "BB",
publishers: {
GVM: {
ask: 11,
bid: 99
},
SET: {
ask: 23,
bid: 34
}
}
}]
So when you use
{{#each priceData}}
...
{{/each}}
you dive into the context of what the helper returns and iterate over items of the array. For example, the first one would be
{
contract: "nn",
publishers: {
GVM: {
ask: 1,
bid: 2
},
SET: {
ask: 6,
bid: 3
}
}
}
Next what you do is
{{#with publishers}}
...
{{/with}}
For the first item of array the context is
GVM: {
ask: 1,
bid: 2
},
SET: {
ask: 6,
bid: 3
}
and for the second is
GVM: {
ask: 11,
bid: 99
},
SET: {
ask: 23,
bid: 34
}
Then you're trying
{{ask}}
and this is where your code fails because there's no ask property of the structure within current context. But there are properties GVM and SET. So pick one you like and use it like this:
{{GVM.ask}}
Hope it helps.

How to do foreach in Meteor with Mongo?

Have collection
Peoples = new Mongo.Collection('peoples');
Peoples.insert({
name: ["Mark", "John", "Kate"]
});
I want to show all names in name
<template name="pTable">
<tr class="trJob">
<td>
{{#each names}}
{{> peopleName}}
{{/each}}
</td>
</tr>
</template>
<template name="peopleName">
<div>{{name}}</div>
</template>
What in my Temlate helpers
Template.pTable.helpers({
names: function(){
return Posts.tags;
}
});
Template.peopleName.helpers({
name: function(){
return Posts.tags.find();
}
});
I know that i have sh*** code in my Template helpers, any idea how to make it good ?
It must look like (in DOM)
<td>
<div>Mark</div>
<div>John</div>
<div>Kate</div>
</td>
simple array example
Template.home.helpers({
names: function(){
return [1,2,3];
}
});
<template name="home">
{{#each names}}
{{this}}
{{/each}}
</template>
will print:
1 2 3
each item becomes "this" inside the each loop. if you call another template within the loop, then its "this" will be populated by the item
Since you have different names for your collection, I will stick with the first one Peoples
Here is how I would proceed with your helpers:
Template.pTable.helpers({
names: function(){
return People.find({_id:yourId},{fields:{name:1}}).fetch();
}
});
And your peopleName template would be like this:
<template name="peopleName">
<div>{{this}}</div>
</template>
If you need to get all the names of all your documents, I need to nest your {{#each names}} into another {{#each doc}} where doc helper is like this (updated names as well) :
Template.pTable.helpers({
doc: function(){
return People.find().fetch();
},
names: function(){
return People.find({_id:this.id},{fields:{name:1}}).fetch();
});

Get value by name with handlebars

I have a huge table with too many columns to fit on-screen. I want the user to be able to select which columns to show using checkboxes. The checkboxes part is easy but I'm not sure how to show the table using handlebars. Is there some helper I could make that would help? I'm using Meteor.js.
{stats:
{symbol: 'A', stat1: 5, stat2, 24.3, stat3: 293, stat4: 3},
{symbol: 'B', stat1: 4, stat2, 24.3, stat3: 293, stat4: 3},
{symbol: 'C', stat1: 2, stat2, 24.3, stat3: 293, stat4: 3}
}
{columns:
{key: 'stat1', name: 'Stat 1'},
{key: 'stat2', name: 'Stat 2'},
{key: 'stat3', name: 'Stat 3'},
{key: 'stat4', name: 'Stat 4'}
}
{currentUser: {columnsToShow: ['stat1', 'stat3']}}
<table>
{{#each stats}}
<tr>
<td>{{symbol}}</td>
{{#each columns}}
{{#if inArray key currentUser.columnsToShow}}
<td>
{{!-- the following is what i'm not sure how to do --}}
{{stats[key]}}
</td>
{{/if}
{{/each}}
</tr>
{{/each}}
</table>
inArray is a helper I made that returns true if it finds key in the array or false if it doesn't.
Here's what I expect the table to look like
A 5 293
B 4 293
C 2 293
EDIT: got it to work
{{#if inArray key currentUser.columnsToShow}}
<td>
{{returnArrayValueByKeyName key ../../this}}
</td>
{{/if}}
Handlebars.registerHelper('returnArrayValueByKeyName', function(keyName, array) {
return array[keyName];
})
You can change your columns helper to a stats_to_show helper that returns the stats for just the columns that you want:
<table>
{{#each stats}}
<tr>
<td>{{symbol}}</td>
{{#each stats_to_show}}
<td>
{{this}}
</td>
{{/each}}
</tr>
{{/each}}
</table>
The stats_to_show helper would look like this
Template.stats_table.stats_to_show = function() {
result = [];
for (column in currentUser.columnsToShow) {
// We're using the fact that a single element of stats is bound to
// `this` when this helper is called.
result.push(this[column];
}
return result;
}
Sorry if my Javascript syntax is off. I've been exclusively using Coffeescript lately.

Resources