How to create html list from a json file (handlebars) - javascript

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

Related

json data getting from url is not parsed in handlebars.js

I want to parse JSON data that I am getting from url in handlebars.
What I tried is I got the JSON data from the url.
I defined it into data object.
I want to know how can I parse the data using handlebars.js
I am new to handlebars.js
Is there any other way in which we can get without defining each property?
Because my JSON data is huge.
for eg.
reportData = {
inquiryId= data.data[0].inquiryId;
}
HTML code:
<script id="address-template" type="text/x-handlebars-template">
{{#with data}}
<p> My id is {{{inquiryId}}}</p>
{{/with}}
</script>
<div class="content-placeholder"></div>
JS code:
var reportData= {};
$(document).ready(function () {
$.ajax({
type:'GET',
url: reportURL,
success : function (data){
var inquiryId= data.data[0].inquiryId;
var theTemplateScript = $("#address-template").html();
console.log(theTemplateScript);
// Compile the template
var theTemplate = Handlebars.compile(theTemplateScript);
// Define our data object
reportData=data;
console.log(reportData);
// Pass our data to the template
var theCompiledHtml = theTemplate(reportData);
// Add the compiled html to the page
$('.content-placeholder').html(theCompiledHtml);
}
})
});
JSON:
{
"success":true,
"errors":{
},
"authenticated":true,
"program":1,
"data":[
{
"id":1,
"date":1505756267000,
"name":"AKKAYA, JORGE",
"productName":"Credit Profile",
"inquiryId":726608
}
]
}
My output is:
My id is
Can anyone help me out?
Thanks in advance.
In your Json, data contains array and in your html you are treating it like single object. So please use the below handlebar format to iterate over it.
{{#with abc}}
{{#each this}}
<p> My id is {{{inquiryId}}}</p>
{{/each}}
{{/with}}

Getting compiled html from template in AngularJS

I must confess that it's not easy to find some basic and easy to understand guide about compiling templates in AngularJS.
Here is the deal:
In my main html-page I have this:
<div>
<div data-ng-include="'./views/testTemplate.html'"></div>
</div>
<div>
<input type=button ng-click="func()" />
</div>
testTemplate.html contains this:
hello {{myname}}
Im my javascript-controller I have this:
$scope.myname = 'max';
Now, when I view the page I see the text "hello max".
Im my javascript-controller I also have this:
$scope.func = function(){
var newScope = $scope.$new();
var newElem = '<ng-src><div ng-include="\'./views/testTemplate.html\'" ></div></ng-src>';
$compile(newElem)(newScope);
console.log('newElem');
console.log(newElem);
});
In the console I can see this:
newElem
<ng-src><div ng-include="'./views/testTemplate.html'" ></div></ng-src>
So, the template is not getting compiled? What am I missing?
***************EDIT***************
The thing is that Im trying to print to console the content of the new element because it needs to be mailed. So I need to send a mail with the compiled content from the template.
Having looked at the answers below, I now have this:
var newElem = '<ng-src><div ng-include="\'./views/testTemplate.html\'" ></div></ng-src>';
var compiledElem = $compile(newElem)(newScope);
console.log('compiledElem[0]');
console.log(compiledElem[0]);
If I use this:
$window.location.href = 'mailto:mailmail.com?subject=sub&body=' + compiledElem[0].innerHTML;
then the body of the mail contains this (uncompiled template):
<!-- ngInclude: './views/matching/testTemplate.html' -->
If I use this:
$window.location.href = 'mailto:mailmail.com?subject=sub&body=' + compiledElem[0];
then the body of the mail contains this:
[object HTMLElement]
So none of them is showing the html-content in the mail I want to send. I know its not exactly the original question, but it was a part of the issue.
I think the variable 'newElem' is not modified by the $compile command. It has a return value which you should use.
var compiledElement = $compile(newElem)(newScope);
console.log('compiledElement');
console.log(compiledElement);
You are missing adding your HTML to the DOM.
$scope.func = function(){
var newScope = $scope.$new();
var newElem = '<ng-src><div ng-include="\'./views/testTemplate.html\'" ></div></ng-src>';
//Append to DOM
document.querySelector('#some-id').append($compile(newElem)(newScope));
console.log('newElem');
console.log(newElem);
});
In my example I'm using document.querySelector that is raw js. But we can use the $element service, or if we are in a directive's link function, it receives a param representing the current element where the directive is being applied.
EDIT:
If you want to send your compiled HTML in an email, then, you will need to wait until all the $digest finish to compile your template.
$scope.func = function(){
var newScope = $scope.$new();
var newElem = angular.element('<ng-src><div ng-include="\'./views/testTemplate.html\'" ></div></ng-src>');
$compile(newElem)(newScope);
$timeout(function(){
$window.location.href = 'mailto:mailmail.com?subject=sub&body=' + newElem.html();
//console.log('newElem');
//console.log(newElem.html());
});
});
Create your template using angular.element, use $timeout to wait until the end and then use newElem.html();.

Ember - Asynchronous data in nested view

I have a list of messages. When a particular message is clicked it loads the details. This part works fine.
I want to load some other related data asynchronously when the clicked message is loaded. For that I'm nesting a view inside my messageView. However I am unable to load and access the data.
Here is my template
<script type="text/x-handlebars" id="message">
{{#view "messageThread" contentBinding="this"}}
{{#each message in view.getConversation}}
<div>Message body</div>
{{message.body}}
{{/each}}
</div>
{{/view}}
</script>
Here is the messageThreadView used in the template above
App.MessageThreadView = Ember.View.extend({
getConversation: function(){
var msg = this.get('context').model;
var sender_id = msg.sender.id;
var recipient_id = msg.recipient.id;
downloadConversation(recipient_id, sender_id);
return this.get('current_conversation');
}.property('current_conversation'),
});
Here is the asynchronous data load function called in the view above
function downloadConversation(recipient_id, sender_id){
$.getJSON(<a url>)
.then(function(data){
App.set('current_conversation', data['objects']);
});
}
How do I get view.getConversation to work as expected i.e load the data when it becomes available?
Here's the simplest pattern for asynchronous properties, especially when they are a collection. You essentially return a collection reference (in this case convo), then you asynchronously populate that collection from the reference.
App.MessageThreadView = Ember.View.extend({
getConversation: function(){
var msg = this.get('context').model,
sender_id = msg.sender.id,
recipient_id = msg.recipient.id,
convo = [];
$.getJSON(<a url>).then(function(data){
data.forEach(function(item){
convo.pushObject(item);
});
});
return convo;
}.property(), // this should be watching sender and receipient
});

Handlebars - data not being displayed at all

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();
});

Automatic two way binding with Knockout

I'm just getting started with Knockout.js and i have a view(html) which is supposed to be populated by data from a rest api via jquery's $.getJSON method.
When i run the app, nothing shows but using firebug i can see that the 'GET' query returns a status code of 200 and the right data.
I'm at a fix as to why nothing shows in the view since the bindings in Knockout.js are supposed to be automatic.
Below is my code.
Thanks
<div id ='main'>
<!-- ko foreach: posts -->
<p>Hello</p><span data-bind="text: title"></span></p><p data-bind="text: content"></p>
<p data-bind="text: author"></p><p data-bind="text: date"></p>
<!-- /ko -->
</div>
</body>
<script type="text/javascript">
function Post(data){
this.title = ko.observable(data.title);
this.content = ko.observable(data.content);
this.author = ko.observable(data.author);
this.date = ko.observable(data.date)
}
function PostListViewModel(){
var self = this;
self.posts = ko.observableArray([]);
$.getJSON("/posts", function(getPost){
var mappedPost = $.map(getPost, function(item){
return new Post(item)
});
self.posts(mappedPost);
});
}
var postlistviewmodel = new PostListViewModel();
ko.applyBindings(postlistviewmodel);
</script>
This should be:
$.getJSON("/posts", function(getPost){
var mappedPosts = $.map(getPost, function(item){
return new Post(item)
});
self.posts(mappedPosts);
});
wouldn't do self.posts.push(mappedPosts[i]) at all. You should just pass mappedPosts through the ko binding in order to update the listeners.
If your just getting the latest posts and want to update your current list simply do:
var allPosts = self.posts().concat(mappedPosts);
self.posts(allPosts);
You don't need the model to have ko.observable if you're just displaying them. If you want to edit model as well, then leave as.
Also, I tend to do this for single or multiple view models:
ko.applyBindings({viewModel : new viewModel() };
This allows for having multiple named view models. Access scope using: $root.viewModel
This is what I did earlier: http://jsfiddle.net/jFb3X/
Check your code against this fiddle then.
Script tags also need to be above the closing body tags
<html>
<head>
</head>
<body>
<!-- all your html content -->
<script type="text/javascript">
var viewModel = function () {
}
ko.applyBindings({viewModel : new viewModel()});
</script>
</body>
</html>
Is it something as simple as waiting for the DOM to be ready?
Are you able to try the following:
$(function () {
ko.applyBindings(postlistviewmodel);
});
Source: I've done this a few times and been stumped for a bit trying to see what I did wrong. :-)
(As a style thing, I'd also move the /body to after the /script - probably not related to your issue though).
I suspect you get multiple posts from /posts. You only push a single item (array).
...
$.getJSON("/posts", function(getPost){
var mappedPosts = $.map(getPost, function(item){
return new Post(item)
});
for(var i = 0; i < mappedPosts.length; i++) {
self.posts.push(mappedPosts[i]);
}
});
...

Categories

Resources