How can I render data in a table using Handlebars? - javascript

I am trying to figure out how to render some data in a table using Handlebars.
I already have the part for the header.
I did it like this:
<thead>
<tr>
{{#each chart.table-header}}
<th>
{{#if th-image.length}}
<p><img src="/assets/images/{{th-image}}" alt=""></p>
{{/if}}
<strong>{{{th-title}}}</strong>
<p>{{{th-description}}}</p>
</th>
{{/each }}
</tr>
</thead>
And here my chart.json:
{
"table-header" : [
{
"th-title": "",
"th-description": "",
"th-image": "",
"special-case": ""
},
{
"th-title": "Online Investing",
"th-description": "Make more informed...",
"th-image": "MESDicon.png",
"special-case": ""
},
{
"th-title": "Merrill Edge Guided Investing",
"th-description": "Go online to...",
"th-image": "MEGIicon.png",
"special-case": ""
},
{
"th-title": "Invest with an advisor",
"th-description": "Get professional...",
"th-image": "MEACicon.png",
"special-case": ""
}
],
"table-body" : [
{
// HERE GOES THE INFO FOR THE TBODY ELEMENT.
}
]
}
But for the rest of tbody part I don't know how can I render the rest of the info.
It should look like this:
But the idea is to render that data coming from the chart.json file.
<tbody>
<tr>
<td>Investing method</td>
<td>Online</td>
<td>Online with professional portfolio management</td>
<td>With an advisor</td>
</tr>
<tr>
<td>Simple, straight-forward pricing</td>
<td><strong>$6.95 online equity & ETF trades<sup>3</sup></strong><br>(Qualify for $0 trades with Preferred Rewards)<sup>2</sup> Other fees may apply<sup>3</sup> </td>
<td><strong>0.45% annual fee</strong><br>Other fees may apply</td>
<td><strong>0.85% annual program fee</strong><br>Other fees may apply</td>
</tr>
<tr>
<td>Minimum investment</td>
<td><strong>None</strong></td>
<td><strong>$5,000</strong></td>
<td><strong>$20,000</strong></td>
</tr>
<tr>
<td>Investment choices</td>
<td><strong>Full range of investments</strong></td>
<td><strong>A set of ETF strategies</strong></td>
<td><strong>A set of mutual fund/ETF strategies</strong></td>
</tr>
<tr>
<td>Bank & invest with one login</td>
<td>✓</td>
<td>✓</td>
<td>✓</td>
</tr>
</tbody>
Any suggestions?

since your table-body is array of objects. you can loop through that and using keys you can access data.
<thead>
<tr>
{{#each chart.table-header}}
<th>
{{#if th-image.length}}
<p><img src="/assets/images/{{th-image}}" alt=""></p>
{{/if}}
<strong>{{{th-title}}}</strong>
<p>{{{th-description}}}</p>
</th>
{{/each }}
</tr>
</thead>
<tbody>
{{#each chart.table-body}}
<tr>
<td>{{this.your_key}}</td>
<td>{{this.your_key}}</td>
<td>{{this.your_key}}</td>
<td>{{this.your_key}}</td>
</<tr>
{{/each}}
</tbody>

Use below code snippet to resolve the issue:
<thead>
<tr>
{{#each table-header}}
<th>
{{#if th-image.length}}
<p><img src="/assets/images/{{th-image}}" alt=""></p>
{{/if}}
<strong>{{th-title}}</strong>
<p>{{th-description}}</p>
</th>
{{/each }}
</tr>
</thead>
<tbody>
{{#each table-body}}
<tr>
<td>{{key1}}</td>
<td>{{key2}}</td>
<td>{{key3}}</td>
<td>{{key4}}</td>
</<tr>
{{/each}}
</tbody>

The problem is that you are not enclosing your handlebars in a <script> tag. Handlebars will compile the template incorrectly without throwing any errors. For div it works always it seems.
Thus simply wrap the template section in a script tag like so:
<script type="text/x-handlebars-template" id="carBladeTemplate">
{{#each cars}}
<tr class="carItem" data-car-id="{{Id}}">
<td>{{Id}}</td>
<td>{{Make}}</td>
<td>{{Model}}</td>
</tr>
{{/each}}
</script>

Related

Handlebars lookup helper to build dynamic tables

I would like to build a dynamic table using handlebars. I think I have to use lookup helper to achieve my wanted result. I am having some trouble using the lookup helper and the documentation is rather poor.
An example of my object looks like this:
{
headers:[
0:"name",
1:"brand",
2:"type",
3:"rating",
4:"edited"
]
tableContent:[
0:{
contentName:{
name:"Fanta",
brand:"Coca-Cola Company",
type:"Soda",
rating:"3",
edited:"2017-05-24"}
}
]
}
Handlebars template:
<script id="itemTemplate" type="text/x-handlebars-template">
<table id="table" class="bordered highlight centered">
<thead>
<tr>
{{#headers}}
<th>{{this}}</th>
{{/headers}}
</tr>
</thead>
<tbody>
<tr>
{{#each tableContent}}
{{#each headers}}
<td>{{lookup ../contentName headers}}</td>
{{/each}}
{{/each}}
</tr>
</tbody>
</table>
</script>
The reason I can't simply do <td> contentName.name </td> and so on, is that the user can create their own columns in the database, so I would have no way of knowing the property names beforehand.
With a little modification in your object, you can do it with ember-contextual-table.
Here is the twiddle for you.
Sample code:
{{#data-table data=data.tableContent as |t|}}
{{#each data.headers as |columnName|}}
{{t.column propertyName=columnName name=columnName}}
{{/each}}
{{/data-table}}
Updated
But if you want to make your code run, here it is:
<table class="bordered highlight centered">
<thead>
<tr>
{{#each data.headers as |header|}}
<th>{{header}}</th>
{{/each}}
</tr>
</thead>
<tbody>
<tr>
{{#each data.tableContent as |c|}}
{{#each data.headers as |h|}}
<td>{{get c h}}</td>
{{/each}}
{{/each}}
</tr>
</tbody>
</table>
Have a look at this twiddle

How to move item in collection in meteor?

I have a wait list type application I am creating. I currently have it where my table will populate with the collection. I want to be able to press a button and that row in the table be moved to the bottom of the table. Here is where the table is populated.
<tbody>
{{#each student}}
<tr class="accordion-toggle mainRow"> <!--mainRow if want whole row to change green-->
<td>{{> expandButton}}</td>
<td>{{Name}}</td>
<td>{{PhoneNumber}}</td>
<td>{{VipID}}</td>
<td class="selectionChange">{{> buttonSelections}}</td>
</tr>
<tr>
<td colspan="12" class="hiddenRow">
<div class="accordian-body collapse" id="{{this._id}}">
<table class="table table-striped">
<thead id="innter-table">
<tr class="info">
<th id="inner-heading">Reason for Visit</th>
<th id="inner-heading">Current Major</th>
<th id="inner-heading">Intended Major</th>
<th id="inner-heading">Comments</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ReasonForVisit}}</td>
<td>{{CurrentMajor}}</td>
<td>{{IntendedMajor}}</td>
<td>{{Comments}}</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
{{> autoformModals}}
{{/each}}
</tbody>
Here is the template for the button:
<template name="buttonSelections">
...//other code for different buttons
<button class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-arrow-down"></span>
</button>
... //other code for different buttons
</template>
I know I'll need some type of event for the button. but I'm not sure how to go about getting the item in the collection to move in the collection so that when it populates the table again, it will move to the bottom.
How do I get the collection to reorder itself so that the selected item will move to the end of the collection?
you won't "move" the item in your collection, what you'll do is sort the collection on the client so it shows how you want. i don't see the relevant helper, but it would all look something like this:
<template name="Students">
{{#each student in students}}
{{student.name}}
{{/each}}
</template>
in the JS, it's pretty standard stuff: subscribe to the collection in the onCreated(), then the helper sorts the collection how you want. here, i'm making up a field, "waitListedTime", by which the collection sorts. your button press could timestamp it for the selected student, and the helper would run reactively and your student list would update on screen.
Template.Students.onCreated(function() {
this.subscribe('students');
});
Template.Students.helpers({
students() {
return Students.find({}, {sort: {waitListedTime: 1}});
}
});

Ember js: How to pass param when render template

I want to pass a param like this from template to controller or route.
<script type="text/x-handlebars" data-template-name="plan">
<table class="table table-bordered">
<thead>
<tr>
<th>Truck Number</th>
<th>Driver Name</th>
<th>Trip 1</th>
<th>Trip 2</th>
</tr>
</thead>
<tbody>
{{#each truck in model}}
<tr>
<td>{{truck.truckNumber}}</td>
<td>{{truck.driverName}}</td>
<td>{{render "plan.trip" truck.shipments trip=1}}</td>
<td>{{render "plan.trip" truck.shipments trip=2}}</td>
</tr>
{{/each}}
</tbody>
</table>
</script>
<script type="text/x-handlebars" data-template-name="plan/trip">
<ul>
{{#each shipment in tripShipment}}
<li>{{shipment.routeCode}}</li>
{{/each}}
</ul>
</script>
Trp.PlanTripController = Ember.ArrayController.extend({
trip: '',
tripShipment: function() {
return this.filterBy('trip', this.get('trip'));
}.property('#each.trip')
});
But this this.get('trip') do not work. How can I render this template with trip as parameter?
Use query-params with a link-to helper in your template, sort of like this. In this case trip is a bound variable, but you could also put it in quotes to pass a specific value.
{{#each truck in model}}
<tr>
<td>{{truck.truckNumber}}</td>
<td>{{truck.driverName}}</td>
<td>{{#link-to "trucks" query-params=trip}}trip 1{{/link-to}}</td>
<td>{{#link-to "trucks" query-params=trip}}trip 2{/link-to}}</td>
</tr>
{{/each}}

Decelerate Meteor page rendering for helper function

I want to count the position of table children using jQuery in a Meteor JS helper function, but I always get an empty result, because the helper function returns before the table data gets inserted.
Here is my code:
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Game</th>
</tr>
</thead>
<tbody>
{{#each games}}
{{> game}}
{{/each}}
</tbody>
</table>
<template name="game">
<tr>
<td>{{counter}}</td>
<td>{{name}}</td>
</tr>
</template>
Template.game.helpers({
counter: function() {
return $('table.table tbody tr td:contains("this.name")').index();
}
});
It should be like:
1 Test
2 ABC
3 HelloWorld
...
Any help would be greatly appreciated.
The idea for solution is that you add to array of games objects additional field called index.
Later in game template you simply use {{index}}.
Below code should solve your issue:
var games_with_index = Games.find().map(function(document, index){
document.index = index;
return document;
});
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Game</th>
</tr>
</thead>
<tbody>
{{#each games_with_index}}
{{> game}}
{{/each}}
</tbody>
</table>
<template name="game">
<tr>
<td>{{index}}</td>
<td>{{name}}</td>
</tr>
</template>
See also this:
Print the loop index in Meteor.js templates

Use of rowspan to group hierarchical data

Is it possible to group data (using rowspan as explained here) in a table rendered with angularjs. Data is hierarchical, with state having many counties and each counties has multiple zipcodes. I want a table with only column for state, county, zip etc (so give a rowspan for length of the collection). I am not sure ng-repeat-start and ng-repeat-end can be used to achieve this. Please see the starter template here
<table>
<thead>
<tr>
<th>State</th>
<th>County</th>
<th>Zip</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='st in states'>
<td>{{st.name}}</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
data
var oh_counties = [
{name: "Franklin", zips: [111,222,333,444,555]},
{name: "Adams", zips: [111,222,333,444]},
{name: "Allen", zips: [111,222,333]}
],
wi_counties = [
{name: "Dane", zips: [111]},
{name: "Adams", zips: [111,222,333,444]}
]
$scope.states = [
{name: "OH", counties: oh_counties},
{name: "WI", counties: wi_counties},
];
Edit:
A handcrafted version of the desired output is here http://plnkr.co/edit/T7toND0odx6qr8mVC121?p=preview
This is a variant of Holly Cummins' answer. The repeat is moved into the tr with ng-repeat-start and ng-repeat-end to prevent the tbody from being repeated. Also uses a slightly different method to hide the first row.
<tbody>
<tr ng-repeat-start='st in states'>
<th rowspan="{{st.counties.length}}">{{st.name}}</th>
<td>{{st.counties[0].name}}</td>
</tr>
<tr ng-repeat-end ng-repeat='county in st.counties' ng-hide="$first">
<td>{{county.name}}</td>
</tr>
</tbody>
This variant of KayakDave's answer improves the structuring by pulling the first nested row out to share the <tr> of the header:
<tbody ng-repeat='st in states'>
<tr>
<th rowspan="{{st.counties.length}}">{{st.name}}</th>
<td>{{county[0].name}}</td>
</tr>
<tr ng-repeat='county in st. counties' ng-show="$index > 0">
<td>{{county.name}}</td>
</tr>
</tbody>
Sure. Is something like this what you had in mind:
<tbody ng-repeat='st in states'>
<td rowspan="{{st.counties.length+1}}">{{st.name}}</td>
<tr ng-repeat='county in st.counties'>
<td>{{county.name}}</td>
</tr>
</tbody>
I kept this example simple, nested 2 deep. But in the fiddle, below, I've got it nested 3 deep (so it includes zip).
demo fiddle
This may be usefull
<table>
<tbody ng-repeat='st in states'>
<tr>
<th >{{st.name}}</th>
<td>
<table>
<tr ng-repeat='county in st.counties'>
<td>{{county.name}}</td>
<td>
<table>
<tr ng-repeat='zip in county.zips'>
<td>{{zip}}</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>

Categories