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
Related
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}}
Is it possible to auto-print the fields of a Meteor collection using helpers without specifying them?
Let's say I start having a helper that returns the collection of objects stored in a table, as follows:
{{ #each CollectionData }}
<thead>
<tr>
<th>Code</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<Tr class="object-row">
<Td> {{code}} </ td>
<Td> {{description}} </ td>
</tr>
</tbody>
...
{{/each}}
Now i specify an "object schema" for each collection to set which field i want to auto-print, pseudo example:
// Items is the name of the possible collection
Schema.items var = {
fields {
code: {
columnName: "code",
show: false,
},
description: {
columnName: "description",
show: false,
},
otherField {
columnName: "foo",
show: false,
}
}
}
Now, I would make the helper to auto-generate the table columns and values of a collection field where the show check is true, without having to manually specify {{code}}, {{description}} and so on, pseudo example:
{{ #each CollectionData }}
<thead>
<tr>
{{print each column where show check is == true, without manually specifing any name}}
</tr>
</thead>
<tbody>
<Tr class="object-row">
{{print the value of the column, for this record, where show check is == true, without specifing its name}}
</tr>
</tbody>
...
{{/each}}
Is there any way to do that?
The simpliest way would be to create a template for each TD, something like
<thead>
<tr>
{{#each fetchColumnHeaders}}
{{> columnHeader }}
{{/each}}
</tr>
</thead>
{{ #each CollectionData }}
<tbody>
<Tr class="object-row">
{{#each fetchColumnItems}}
{{> columnItem}}
{{/each}}
</tr>
</tbody>
{{/each}}
<template name="columnHeader">
<th>{{label}}</th>
</template>
<template name="columnItem">
<td>{{label}}</td>
</template>
And then you can write template helpers to return the column headers, and the various items based on your schema
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.
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}}
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.