Handlebar table createion with 3 inside each helper problem - handlebars.js

Suppose i have 3 dummy array :
let dummyArray = [0,1,2,3,4];
let dummyArray2 = [0,1,2,3];
let dummyArray3 = [{data:'d1'},{data:'d2'}];
and i want create table with these array like this:
<table class="table">
<thead>
<tr>
<th>col-0</th>
<th>col-1</th>
<th>col-2</th>
<th>col-3</th>
<th>col-4</th>
</tr>
</thead>
<tbody>
{{#each dummyArray}}
<tr>
<td>row</td>
{{#each ../dummyArray2}}
<td>
{{#each ../../dummyArray3}}
{{this.data}}
{{/each}}
</td>
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
but i get unexpected result, some cells in the table are empty.
Demo: https://jsfiddle.net/PouyaAk/m7g31e8y/32/

Use of #root is solving the problem, see below, however it's still intriguing to me why your code works that way - but I haven't used handelbarsjs for a quite while
<table class="table">
<thead>
<tr>
<th>col-0</th>
<th>col-1</th>
<th>col-2</th>
<th>col-3</th>
<th>col-4</th>
</tr>
</thead>
<tbody>
{{#each dummyArray}}
<tr>
<td>row</td>
{{#each #root.dummyArray2}}
<td>
{{#each #root.dummyArray3}}
{{this.data}}
{{/each}}
</td>
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
Edit:
the code below fills only previously empty cells, leaving the rest of them empty
... strange
<tbody>
{{#each dummyArray}}
<tr>
<td>row</td>
{{#each ../dummyArray2}}
<td>
{{#each ../dummyArray3}}
{{this.data}}
{{/each}}
</td>
{{/each}}
</tr>
{{/each}}
</tbody>

Related

Handlebars - Passing data with each

I am trying to center one of the td in table while each helper. Is it possible to do so?
Below is my code:
<table>
<thead>
<tr>
{{#each item.[0]}}
<th>{{#key}}</th>
{{/each}}
</tr>
</thead>
<tbody>
{{#each item}}
<tr>
<td>{{Name}}</td>
<td>{{Age}}</td>
</tr>
{{/each}}
</tbody>
</table>
I want it to be like this:
<thead>
<tr>
<th>Name</th>
<th style="text-align:center">Age</th>
</tr>
</thead>
<tbody>
<tr>
<td>User 1</td>
<td style="text-align:center">12</td>
</tr>
</tbody>
var theTemplateScript = $("#entry-template").html();
var theTemplate = Handlebars.compile(theTemplateScript);
var context = {
title: "My New Post",
body: "This is my first post!",
item: [{
"Name": "Ayyub",
"Age": 23
}]
};
console.log("context ", context)
var theCompiledHtml = theTemplate(context);
console.log("theCompiledHtml ", theCompiledHtml);
$('.content-placeholder').html(theCompiledHtml);
var html = theTemplate(context);
.Age {
text-align: center;
color: red;
}
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
</head>
<body>
<script id="entry-template" type="text/x-handlebars-template">
<table>
<thead>
<tr>
{{#each item.[0]}}
<th class="{{#key}}">{{#key}}</th>
{{/each}}
</tr>
</thead>
<tbody>
{{#each item}}
<tr>
<td>{{Name}}</td>
<td class="Age">{{Age}}</td>
</tr>
{{/each}}
</tbody>
</table>
</script>
<div class="content-placeholder">
<table>
<thead>
<tr>
{{#each item.[0]}}
<th class="{{#key}}">{{#key}}</th>
{{/each}}
</tr>
</thead>
<tbody>
{{#each item}}
<tr>
<td>{{Name}}</td>
<td class="Age">{{Age}}</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
</body>
You can use this snippet, for reference I have added red color for font which you can remove later from the CSS file. Hope this helps :)

Each cant run twice?

This is somehow a simple issue with handlebars where my TDs are not being rendered.
My Handlebar:
<table class="defaultTable" style="width:90mm;">
<colgroup>
{{#each cols}}
<col style="width:{{this.width}}mm;">
{{/each}}
</colgroup>
<tbody>
{{#each rows}}
<tr>
{{#each cols}}
<td>{{this.content}}</td>
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
My Data:
cols = [{
width: 45,
content: ''
},{
width: 45,
content: ''
}];
Rows = [{},{}];
My Output
<table class="defaultTable" style="width:90mm;">
<colgroup>
<col style="width:45;">
<col style="width:45;">
</colgroup>
<tbody>
<tr>
</tr>
<tr>
</tr>
</tbody>
</table>
Why are the tds not being rendered? Did I miss something regarding how the each loop should work?
Thanks.
I was out of the context block indeed as the comment stated. It was searching for cols inside the rows object. Will post the fix so other ppl with the same issue can see, hope it helps someone.
<tbody>
{{#each rows}}
<tr>
{{#each ../cols}}
<td>{{this.content}}</td>
{{/each}}
</tr>
{{/each}}
</tbody>
The ../ on the cols solved it.

Handlebars loop in loop not working

I have the following handlebars file:
<table>
<tbody>
{{#name_days}}
<tr>
<td class="name-days-country">
<span class="flag-sm flag-sm-{{flag}}"></span>
<span class="name-days-country-name">{{country}}</span>
</td>
<td class="name-day-dates">
{{#each months}}
<td class="name-days-tile">
<span>{{this}}</span>
</td>
{{/each}}
</td>
</tr>
{{/name_days}}
</tbody>
</table>
I'm expecting <td class="name-days-tile"> to be inside <td class="name-day-dates"> but it renders as:
<td class="name-day-dates"></div>
<td class="name-days-tile"></div>
Why isn't it rendering as expected?
The issue ended up being that one cannot put a td inside a td.
While one can manually do it, without it being valid in plain HTML, handlebars detected the issue and automatically applied a closing </td> before adding another opening <td> during the render process.

Footable 2 Select rows

I'm using FOOTABLE to create job board. What I want to add is a checkbox option to select jobs (rows) so users can send cv to multiple jobs at once. Any idea on how to implement this in existing table?
simple example:
<table class="footable toggle-arrow" data-page-size="20" >
<thead>
<tr>
<th><!--select option id col--></th>
<th><span>Job Description</span></th>
<th><span>Area</span></th>
<th><span>Number</span></th>
<th><!--TYPE--></th>
<th><!--SEND--></th>
</tr>
</thead>
<tbody>
<tr><!---JOB-->
<td><input type="checkbox" value="id"></td>
<td>job description value</td>
<td>area value</td>
<td>job number</td>
<td data-value="4566">4566</td>
<td data-value="3"><img title="hot" src="vip.png" /></td>
<td></td>
</tr><!---END JOB-->
</tbody>
Thanks!
Here's a quick example of one way you could do this:
<!DOCTYPE html>
<html>
<head>
<script data-require="jquery#*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<a id="sendSelectedButton" href="#">Send Selected</a>
<table id="theTable">
<thead>
<tr>
<th></th>
<th>Description</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="checkbox">
</td>
<td>Job 1</td>
<td>send
</td>
</tr>
<tr>
<td>
<input type="checkbox">
</td>
<td>Job 2</td>
<td>send
</td>
</tr>
<tr>
<td>
<input type="checkbox">
</td>
<td>Job 3</td>
<td>send
</td>
</tr>
</tbody>
</table>
<script>
function sendRows(rows) {
if (rows === undefined ||
rows === null ||
rows.length === 0)
return;
//Do stuff to send rows here.
}
$(document).ready(function() {
$("#sendSelectedButton").on("click", function() {
var checkRows = $("#theTable").find("tbody tr").has("input:checked");
sendRows(checkRows);
});
$("table").on("click", "tr a", function() {
var row = $(this).parents("tr");
sendRows(row);
});
});
</script>
</body>
</html>
Here's a plunk with the same code: http://plnkr.co/edit/tK4WpCvV7vSjVFmKlJIx
I didn't add any Footable here because it doesn't seem like that Footable will affect it one way or another.
I think you'll find that things quickly get a lot more complex as your application matures. I'd suggest you look some type of data binding. I personally use Knockout.js. Even if you don't decide to use Knockout.js, I think their tutorial is pretty cool. (http://knockoutjs.com/index.html)

Static row above knockout.js observable array table

I have a html table and the rows come form an observable array....
<tbody data-bind="foreach: TableArray">
<tr>
<td data-bind:"text: Item1"></td>
etc....
How can I skip the first row... so I can add a static row (not a header) to the top of the table.
<tbody data-bind="foreach: TableArray">
<tr>
<td> Static Row </td>
</tr>
<tr>
<td data-bind:"text: Item1"></td>
The secret is in the containerless foreach markup. Check "Note 4" of the following link:
http://knockoutjs.com/documentation/foreach-binding.html
Here's a fiddle showing a basic example.
http://jsfiddle.net/internetH3ro/M9f4D/7/
Basic view model:
function ViewModel() {
var self = this;
self.items = [{
firstName: 'James',
lastName: 'McConnell'
},{
firstName: 'Scott',
lastName: 'Hanselman'
},{
firstName: 'Bill',
lastName: 'Gates'
}];
}
HTML markup:
<table>
<tr>
<th>First Name</th>
<th>Last Name</th>
</tr>
<!-- ko foreach: items -->
<tr>
<td><span data-bind="text: $data.firstName"></span></td>
<td><span data-bind="text: $data.lastName"></span></td>
</tr>
<!-- /ko -->
</table>
So you just wrap the content you want repeated in a comment, and Knockout will repeat that content for each element in your collection. Pretty nifty, I wish Angular had something like this.
One way to approach the issue would be to use Knockout's containerless binding syntax.
See Note 4 in Knockout's documentation of the foreach binding.
http://knockoutjs.com/documentation/foreach-binding.html
Javascript
var YourVM = function () {
this.allItems = ko.observableArray(["Fries", "Eggs Benedict", "Ham", "Cheese"]);
};
ko.applyBindings(new YourVM());
HTML
<table>
<thead>
<tr>
<th>Your Column</th>
</tr>
</thead>
<tbody>
<tr class="row-static">
<td>Static Row</td>
</tr> <!-- ko foreach: allItems -->
<tr>
<td data-bind="text: $data"></td>
</tr> <!-- /ko -->
</tbody>
</table>
Live example on JS Bin
http://jsbin.com/AzEwEce/1/edit
You could use an if binding to only output an extra row on the "first" pass.
Example:
<table data-bind ="foreach: rows">
<tr data-bind="if: $index() == 0" >
<td><span data-bind="text: $index"></span></td>
</tr>
<tr>
<td><span data-bind="text: text"></span></td>
</tr>
</table>

Resources