I've got an MJML template which compiles to HTML, and am wanting to load variables from a JSON file to the template. I'm new to HTML, JS & Handlebars so could be really off track here.
My MJML template, test.mjml, looks something like:
<mjml>
<mj-body>
<mj-raw><script type="text/javascript" src="handlebars-v4.7.3.js"></script></mj-raw>
<mj-raw><script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script></mj-raw>
<mj-section>
<mj-text><mj-raw>
<script id="test-template" type="text/x-handlebars-template">
<div>
<p>
Hello my name is {{name}}.
</p>
</div>
</script>
</mj-raw></mj-text>
</mj-column>
</mj-section>
I have a JSON file, data.json:
{
"name": "John",
"height": "175cm",
"occupation": "Teacher",
}
And a JS file, test.js:
$(document).ready(function() {
var template = $('#test-template').html();
var compiledTemplate = Handlebars.compile(template);
$.getJSON('data.json', function (data) {
var context = data;
}
});
var html = compiledTemplate(context);
$(document.body).append(html);
Does anyone know how to do this / what I'm doing wrong?
If I replace jQuery's getJSON method with an inline JSON, it works.
I am having my first play with HandlebarsJS and I am looking to use multiple arrays within it. Is this possible?
I have setup a Codepen template but I am struggling to implement the data from 2 arrays and from an external URL. I have tried this with MustacheJS too, but I believe that only allows one array and no filtering- unlike Handlebars
Here is the external JSON
and the CodePen
<!-- REQUIRED - Display site name, url and title in top section. With product data below using the "other array-->
<script id="myTemplate" type="text/x-handlebars-template">
{{content}}
</script>
<div id="contentArea"></div>
<script>
var data = {"content": "Hello, World!"};
var source = $("#myTemplate").html();
var template = Handlebars.compile(source);
var html = template(data);
$("#contentArea").text(html);
</script>
Here is my first template attempt but failing to integrate the JSON array at the moment
It's possible using {{#each}} block helper. I also registered my own helper {{{s}}}, which simply returns it's argument JSON.stringify()'ied, so I can print those arrays. How you fetch them is another problem, I Copy & Paste them into the Javascript part of the code for simplicity. Also, here's JS fiddle:
var data = {"content": "Hello, World!", "multipleArrays": [
[
{
"productimage": "https://c.static-nike.com/a/images/t_PDP_864_v1/f_auto/i0lfddlghaiwfqlvlqay/air-vortex-shoe-fmq6pS.jpg",
"producturl": "https://www.nike.com/gb/t/air-vortex-shoe-fmq6pS"
},
{
"productimage": "https://c.static-nike.com/a/images/t_PDP_864_v1/f_auto/cmuof8adhfipkvd0f43r/air-max-95-shoe-XPTbV2mM.jpg",
"producturl": "https://www.nike.com/gb/t/air-max-95-shoe-XPTbV2mM"
}
],
[
{
"sitename": "Nike",
"sitetitle": "Nike. Just Do It.. Nike.com",
"siteurl": "https://www.nike.com/gb/en_gb/"
}
]
]};
Handlebars.registerHelper('s', function(arg) {
return JSON.stringify(arg);
})
var source = $("#myTemplate").html();
var template = Handlebars.compile(source);
var html = template(data);
$("#contentArea").html(html);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.11/handlebars.min.js"></script>
<!-- REQUIRED - Display site name, url and title in top section. With product data below using the "other array-->
<script id="myTemplate" type="text/x-handlebars-template">
<h1>Content: {{content}}</h1>
<hr>
<h2>Stringified multiple arrays:</h2>
{{{s multipleArrays}}}
<hr>
{{#each multipleArrays}}
<h2>Item {{#index}}</h2>
{{{s this}}}
<br>
<br>
{{/each}}
</script>
<div id="contentArea">
</div>
Let's say I have some model with html field. This field contains some handlebars code. For example
<div class="foo">
{{model.title}}
</div>
The problem is when I'm trying to iterate over models and render html field, it doesn't evaluate handlebars code inside it.
{{#each models as |model|}}
{{{model.html}}}
{{/each}}
Here's an idea, create a Handlebars helper, that will compile handlebars.
With this sample, I believe you can build something that will suit your needs:
<script type="text/javascript" src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars.min-latest.js"></script>
<script>
var data = [{
"title": "Hey",
"subtitle": "I'm an inner handlebar template.",
"html": '<h1>{{title}}</h1><h2>{{subtitle}}</h2>'
}, {
"title": "Nice!",
"html": '<h1>{{title}}</h1>'
}];
/** Handlebar helper that will compile the content passed, with the data at index **/
Handlebars.registerHelper("compile", function(content, index) {
var template = Handlebars.compile(content);
return template(data[index]);
});
var content = '{{#each .}}\
{{{compile html #index}}}\
{{/each}}';
var template = Handlebars.compile(content);
document.body.innerHTML = template(data);
</script>
I never used ember, but I believe you can make it work easily ;)
I have an empty todo list:
<ul class="list">
</ul>
I want to create a li inside that list for each json title I have in the following json data:
[{"id":2,"title":"Mandar cartas a impresión","description":"","status":false,"priority":1,"created_at":"2015-12-07T13:09:55.552Z","updated_at":"2015-12-07T13:09:55.552Z","project_id":1},{"id":3,"title":"CIF Intracomunitario","description":"","status":false,"priority":1,"created_at":"2015-12-07T13:10:05.736Z","updated_at":"2015-12-07T13:10:05.736Z","project_id":1},{"id":4,"title":"Uniformes Chef a Porter","description":"","status":false,"priority":1,"created_at":"2015-12-07T13:10:16.170Z","updated_at":"2015-12-07T13:10:16.170Z","project_id":1},{"id":5,"title":"Personal","description":"","status":false,"priority":1,"created_at":"2015-12-07T13:10:31.569Z","updated_at":"2015-12-07T13:10:31.569Z","project_id":1},{"id":1,"title":"Mandar contrato pleni","description":"","status":false,"priority":1,"created_at":"2015-12-07T13:09:36.747Z","updated_at":"2015-12-07T13:13:12.068Z","project_id":1},{"id":17,"title":"Comprar TPV","description":"","status":false,"priority":null,"created_at":"2015-12-08T00:18:40.753Z","updated_at":"2015-12-08T00:18:40.753Z","project_id":1},{"id":18,"title":"Vajillas Zara Home","description":"","status":false,"priority":null,"created_at":"2015-12-08T00:18:54.580Z","updated_at":"2015-12-08T00:18:54.580Z","project_id":1},{"id":19,"title":"Tpv","description":"","status":false,"priority":null,"created_at":"2015-12-08T00:33:17.393Z","updated_at":"2015-12-08T00:33:17.393Z","project_id":1},{"id":21,"title":"Wifi - Contratar","description":"","status":false,"priority":null,"created_at":"2015-12-08T15:33:24.639Z","updated_at":"2015-12-08T15:33:24.639Z","project_id":1},{"id":22,"title":"Cuenta Definitiva Santander","description":"","status":false,"priority":null,"created_at":"2015-12-08T15:33:50.255Z","updated_at":"2015-12-08T15:33:50.255Z","project_id":1},{"id":23,"title":"Pagarés Kider","description":"","status":false,"priority":null,"created_at":"2015-12-08T15:34:08.162Z","updated_at":"2015-12-08T15:34:08.162Z","project_id":1}]
So, I have the following javascript which uses handlebars for templating:
<script>
jQuery.getJSON("http://myurl/tasks.json", function(data){
var source = $("#tasks-template").html();
var template = Handlebars.compile(source);
$.each(data) function() {
var context = data;
var show = template(context);
$(".list").html(show);
});
});
</script>
My handlebars template:
<script id="tasks-template" type="text/x-handlebars-template">
<li>
<div>{{title}}</div>
</li>
</script>
It wont create a li in my html for each title in the json.
What am I missing?
Thanks!
When you iterate for each object of the array received in the JSON, you have to use this instead of data to access to the object.
data is the whole array and this is the current object where you want to retrieve the title property:
$.each(data, function() {
var context = this;
var show = template(context);
$(".list").append(show);
});
And also change the html method for append for don't overwrite the content.
Regards
Hello everyone,
I've been playing around with the handlebars trying to make it work in my project, but I keep getting no results when I'm testing the page.
I'm using the JSON data that I have received from another page. Those data should be displayed after compiling the template. But nothing really happens, I just get no results at all.
get_items_data.js
var source = $("#mytemplate").html();
var template = Handlebars.compile(source);
var Items = Array();
getting_items_data = true;
$.get('GetItemsData',function(responseJson) {
if(responseJson!=null){
$.each(responseJson, function(key,value) {
Items.push({ "id": value['item_id'], "blabla": "bla" });
});
}
});
$('body').append(template(Items));
test.jsp
<script id="mytemplate" type="text/x-handlebars-template">
<table>
<thead>
<th>Items</th>
</thead>
<tbody>
{{#each this}}
<tr>
<td>{{id}}</td>
<td>{{blabla}}</td>
</tr>
{{/each}}
</tbody>
</table>
</script>
JSON data format:
[{"ItemID":74,"SectionID":4},{"ItemID":78,"SectionID":4}]
Any ideas what may be wrong here?
It looks your template function is called before you have the data returned, so the Items array is empty when the elements are appended to the DOM. Unlike AngularJS, Handlebars is static templating so it won't update the DOM if you update the array later.
Try move that render logic into the callback of get:
$.get('GetItemsData',function(responseJson) {
if(responseJson!=null){
$.each(responseJson, function(key,value) {
Items.push({ "id": value['item_id'], "blabla": "bla" });
});
$('body').append(template(Items));
}
});
$(document).ready(function() {
LoadItems();
});
Will never execute inside a script of type text/x-handlebars-template.
Also there could be a problem with your variables attempting to get values from the dom before it's loaded.
Here is a dumbed down version that works: http://jsfiddle.net/whDqv/
function LoadItems()
{
var source = $("#mytemplate").html();
var template = Handlebars.compile(source);
var Items = Array();
getting_items_data = true;
Items.push({ "id": 1, "blabla": "bla" });
var template = Handlebars.compile(source);
$('body').append(template(Items));
}
$(document).ready(function() {
LoadItems();
});