Meteor(spacebars):How to use #with and #each together - meteor

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.

Related

Handlebars HBS Express - How to iterate an object without specify the properties

I am trying to iterate using the properties of an object to dynamically print a table having an array with the properties and an object with the values ​​of each property.
I don't know how to do the 2 iterations using hbs express from handlebars
people: [{
name: "ken",
lastname: "grace",
age: 10
},
{
name: "ron",
lastname: "bond",
age: 20
}];
properties = ["name","lastname", "age"];
HTML CODE:
<table>
<thead>
<tr>
{{#each properties as |property index|}}
<th>
<span>{{property}}</span>
</th>
{{/each}}
</tr>
</thead>
<tbody>
{{#each people}}
<tr>
{{#each properties}}
<th>
{{!-- trying something like: --}}
{{!-- {{people.property}} --}}
</th>
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
As user #76484 mentioned, you want to use the built-in lookup helper:
The lookup helper allows for dynamic parameter resolution using Handlebars variables. It can be used to look up properties of object based on data from the input.
In your specific example, you'd probably want to store your people and properties iterations in a block parameter (e.g., named |person| and |property|), as well as using ../ on your inner loop since the context has changed.
Putting that all together for you example, the HBS markup might look like:
<table>
<thead>
<tr>
{{#each properties as |property index|}}
<th><span>{{property}}</span></th>
{{/each}}
</tr>
</thead>
<tbody>
{{#each people as |person|}}
<tr>
{{#each ../properties as |property|}}
<th>{{lookup person property}}</th>
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
See this playground link for the resulting HTML as well.

Display row number using {{#each}}

I'm trying to count each row in a table. Each table row is a new collection. The code below counts the total number of collections and displays that. How do I change it to display the row number.
Path: calc.js
SalaryCalculator: function () {
return SalaryCalculator.find({});
},
SalaryCalculatorCount: function () {
return SalaryCalculator.find({}).count();
}
Path: calc.html
{{#each SalaryCalculator}}
<tr>
<th scope="row">{{SalaryCalculatorCount}}</th>
<td>{{specialisation}}</td>
<td>{{subSpecialisation}}</td>
<td>{{positionTitle}}</td>
<td>{{yearsOfExperience}}</td>
<td>{{salary}}</td>
</tr>
{{/each}}
Here's the helpers
SalaryCalculator: function () {
var count = 1;
var salCalDetails = SalaryCalculator.find({});
salCalDetails.forEach(function(doc){
doc.rowCount = count;
count++;
});
return salCalDetails;
},
{{#each SalaryCalculator}}
<tr>
<th scope="row">{{rowCount}} </th>
<td>{{specialisation}}</td>
<td>{{subSpecialisation}}</td>
<td>{{positionTitle}}</td>
<td>{{yearsOfExperience}}</td>
<td>{{salary}}</td>
</tr>
{{/each}}
Or if you follow through the answer given by #Michel Floyd then you need this answer too https://stackoverflow.com/a/22103990/3422755 as {{#index}} will give you starting number as 0

Meteor: Count data from collection

anyone please i need you help. before this I have asking question but I cannit find this solution. I have create code to count variable in collection. I can get the result when count one by one but not by group. Thats my code, I want to count this but the code not given any resut to me. I want the result like this:
PTR 1
KOM 4
This my code:
<template name="laporankategori">
<table class="table">
<thead>
<tr>
<th>Jenis Peralatan</th>
<th>Kuantiti</th>
</tr>
</thead>
<tbody>
{{#each profil}}
<tr>
<td>{{PTR}}</td>
<td>{{KOM}}</td>
</tr>
{{/each}}
</tbody>
</table>
</template>
//js
Template.laporankategori.helpers({
profil: function() {
return Profil.find({kategori: { $in: ['PTR', 'KOM'] } }).count();
}
});
<template name="laporankategori">
<table class="table">
<thead>
<tr>
<th>Jenis Peralatan</th>
<th>Kuantiti</th>
</tr>
</thead>
<tbody>
{{#each profil}}
<tr>
<td>{{count}}</td>
</tr>
{{/each}}
</tbody>
</table>
</template>
//js
Template.laporankategori.helpers({
profil: function() {
var PTR = {
count: Profil.find({kategori: { $in: ['PTR'] } }).count()
};
var KOM = {
count : Profil.find({kategori: { $in: ['KOM'] } }).count()
};
var resultArr = [PTR, KOM];
return resultArr;
}
});
Whenever you're iterating with {{#each ...}} your helper should return either a cursor or an array. Your helper is returning a scalar: the count. In your {{#each }} block you refer to {{PTR}} and {{KOM}} but those won't exist.
I suspect that you weren't actually looking for the count in this case and your helper should just be:
Template.laporankategori.helpers({
profil: function() {
return Profil.find({kategori: { $in: ['PTR', 'KOM'] } });
}
});
Also you don't often need to count things in a helper since in a template you can refer to {{profil.count}} and get the count of the cursor directly.

Collections not showing on page

I have published a countries collection which I want to show in a table in the countriesList template. So I have added this to the router:
Router.route('/countries_list', {
name: 'countriesList',
waitOn: function() {
return Meteor.subscribe('countries');
},
data: function() {
return Countries.find();
}
});
And this is how the template looks like:
{{#each countries}}
<tr>
<td>{{name}}</td>
</tr>
{{/each}}
But the page stays empty. However, the collection is filled on the client, if I check the browser console and do Countries.findOne();, I get this result:
Object {_id: "WWJhMBne4CiEdbbdg", name: "England"}
So what am I doing wrong here?
You template is making the assumption that the cursor is being stored in coutries. It isn't. It would be if your data hook looked like:
return {countries: Countries.find()};
As your code is written, the cursor is the context for your template so this should work:
{{#each this}}
<tr>
<td>{{name}}</td>
</tr>
{{/each}}

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