I have a simple example with Handlebars, and I cannot get it to work! Please help. I am trying to get the google app engine guestbook to work with handlebars instead of jinja2
HTML/Template code is as follows:
Hello {{user.nickname}}
<h2>Top 10 Most Recent Guestbook Entries</h2>
{{#each greetings}}
<br>
<small>[<i>{{date.ctime}}</i>]</small>
<b>
{{#if author}}
<code>{{author.nickname}}</code>
{{else}}
<i>anonymous</i>
{{/if}}
</b>
wrote:
{{comment}}
{{/each}}
</script>
<div id="comment_content"> </div>
<form id="comments" action="">
<div><textarea id="comment" name="content" rows="3" cols="60"></textarea></div>
<div><input id="comment_button" type="button" value="submit"></div>
</form>
{{ url_linktext }}
and here is the JS code:
<script>
$(document).ready(function() {
var source = $("#entry-template");
var srcHTML =source.html();
var template = Handlebars.compile(srcHTML);
// put all your jQuery goodness in here.
$("#comment_button").click(function(event) {
var data = JSON.stringify({
"login": "/_ah/login?continue=http%3A//localhost%3A8080/show",
"logout": "/_ah/login?continue=http%3A//localhost%3A8080/show&action=Logout",
"user": {
"nickname": "dummy",
"email": "dummy#me.com"
},
"greetings": [
{
"comment": "COMMENT1",
"date": {
"ctime": "Sun Feb 10 23:20:21 2013"
},
"author": {
"nickname": "dummy",
"email": "dummy#me.com"
}
}
]
})
var html = template(data);
console.log(html);
$("#comment_content").html(html);
});
});
</script>
Here is how I am referencing Handlebar source
Can someone please help?
Thanks a mil
Your big problem is that you're using JSON.stringify to prepare your data for the compiled template function:
var data = JSON.stringify({ ... });
var html = template(data);
That will end up handing the template function a string (which is a JSON representation of the data you want) when it wants just the object. Drop the JSON.stringify and things will start behaving better:
var data = { ... };
var html = template(data);
Demo: http://jsfiddle.net/ambiguous/Axmbd/
Also, this part of your HTML:
{{ url_linktext }}
doesn't appear to be inside the template's <script> so the {{url}} and {{url_linktext}} won't be filled in. You can fix that by moving that <a> to the right place.
Related
I am pulling a text from a JavaScript file but the HTML tags don't work.
I followed the best answer here and ran into that problem:
Build multiple language website using jQuery and JSON based methods
This is the part of the JavaScript file:
var arrLang = {
"en-gb": {
"HOME": "Home",
"ABOUT": "About <br> Us",
"CONTACT": "Contact Us",
},
"zh-tw": {
"HOME": "首頁",
"ABOUT": "關於我們",
"CONTACT": "聯絡我們",
}
};
// The default language is English
var lang = localStorage.getItem('lang') || navigator.language.slice(0, 2);
if (!Object.keys(arrLang).includes(lang)){
lang = 'en';
}
// Check for localStorage support
if('localStorage' in window){
var usrLang = localStorage.getItem('uiLang');
if(usrLang) {
lang = usrLang;
}
}
console.log(lang);
$(document).ready(function() {
"use strict";
$(".lang").each(function() {
$(this).text(arrLang[lang][$(this).attr("key")]);
});
});
// get/set the selected language
$(".language-button").click(function() {
"use strict";
var lang = $(this).attr("id");
localStorage.setItem('lang', $(this).attr("id"));
// update localStorage key
if('localStorage' in window){
localStorage.setItem('uiLang', lang);
console.log( localStorage.getItem('uiLang') );
}
$(".lang").each(function() {
$(this).text(arrLang[lang][$(this).attr("key")]);
});
});
HTML: This is how I pull the Text:
<div class="lang" key="ABOUT"></div>
HTML: Expected result:
About
Us
HTML: This is what I get:
About <br> Us
What is a very simple way to make the HTML tags work in this case?
If you use use .innerText in your JavaScript file to put the values into the HTML file, you might want to use .innerHTML instead. This will help if you have tags (like the <br> tag in your situation) in your values.
If you use something else to put the values into the HTML file, please clarify which method you use...
You can find more information about innerHTML vs innerText here.
you're not specifying how you do the replacement, but given your data
var arrLang = {
"en": {
"HOME": "Home",
"ABOUT": "About <br> Us",
"CONTACT": "Contact Us",
},
};
you could simply have:
var arrLang = {
"en": {
"HOME": "Home",
"ABOUT": "About <br> Us",
"CONTACT": "Contact Us",
},
};
var languageSelected = 'en';
var langData = arrLang[languageSelected];
// for each key in your object
Object.keys(langData).forEach(k => {
// search for attribute "key" and add string as HTML
$(`[key=${k}]`).html(langData[k]);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li><div class="lang" key="HOME"></div></li>
<li><div class="lang" key="ABOUT"></div></li>
<li><div class="lang" key="CONTACT"></div></li>
</ul>
What is the proper way to access a nested array of JSON data to be used in Handlebars template file?
My code works in the Dev environment of chrome but doesn't work in Prod.
Here's a sample data of my JSON file.
{
"slider-card-1": [{
"card-img-1": "img/guillermo-rico-1368543-unsplash.jpg",
"card-date-1": "May 29 2019",
"card-title-1": "Deeper dive",
"card-description-1": "Deeper dive into your finances",
"btn-text-1": "Watch video",
"btn-link-1": "vid.co",
"section-header-1": "Be Heard"
},
{
"card-img-2": "img/thought-catalog-685332-unsplash.jpg",
"card-date-2": "May 29 2019",
"card-title-2": "Experience-led Agile",
"card-description-2": "Bringing experiences of our core stakeholders...",
"btn-text-2": "Learn more",
"btn-link-2": "#",
"section-header-2": "Arya"
},
{
"card-img-3": "img/thought-catalog-685332.jpg",
"card-date-3": "Febuary 4 2019",
"card-title-3": "Simplifying terminology",
"card-description-3": "It can be confusing to understand terms.",
"btn-text-3": "Read More",
"btn-link-3": "#",
"section-header-3": "Do it"
}]
}
Code for that goes into the html template file:
<script id="newsletter-template" type="text/x-handlebars-template">
<div>
<div>
<img src={{slider-card-1.[0].card-img-1}}>
</div>
<span>{{slider-card-1.[0].card-date-1}}</span>
<div>
{{slider-card-1.[0].section-header-1}}
</div>
<div>
{{slider-card-1.[0].card-title-1}}
</div>
<div>
{{slider-card-1.[0].card-description-1}}
</div>
<a href={{slider-card-1.[0].btn-link-1}}>
{{slider-card-1.[0].btn-text-1}}
</a>
</div>
</script>
Code to compile the template
<script>
var newsletter_method = {
handlerData: function (resJSON) {
var templateSource = $("#newsletter-template").html(),
template = Handlebars.compile(templateSource),
newsletterHTML = template(resJSON);
$("#my-container").html(newsletterHTML);
},
loadNewsletterData: function () {
$.ajax({
url: "./data.json",
method: 'GET',
success: this.handlerData
})
}
};
$(document).ready(function () {
newsletter_method.loadNewsletterData();
});
</script>
Now when the template is compiled, the generated HTML is blank in the browser. Is there a better way to access the nested array of JSON data in Handlebars? How do I do this?
I'm having a JSON Collection, I wish to dispay Email ID which is marked as IsPreffered = TRUE using AngularJS HTML without .
user.Name
My JSON Collection :
{ "user" : [
{
"Name" : "B. Balamanigandan",
"Email": [
{
"Id": "bala#gmail.com",
"IsPreffered": true
},
{
"Id": "mani#gmail.com",
"IsPreffered": false
}
]}
]};
HTML Source Code:
<div>
<h3>Employee Details:</h3>
<span> {{collection.user.Name}} </span>
<span> {{collection.user.Email.Id}} </span>
</div>
The Collection user contains only one document. So, I didn't use ng-repeat. user is a Collection not a Document. One more check I need. If more than one email has `IsPreferred == true', then I have the take the last one. Kindly assist me.
Kindly filter the condition using HTML Level not in JavaScript Level. Kindly assist me.
instead of this:
<div>
<h3>Employee Details:</h3>
<span> {{collection.user.Name}} </span>
<span> {{collection.user.Email.Id}} </span>
</div>
you will have to do this:
<div>
<h3>Employee Details:</h3>
<span> {{collection.user[0].Name}} </span>
<span ng-repeat="email in collection.user[0].email| filter: {IsPreffered : 'true'}"> {{email.Id}} </span>
</div>
You have to use array syntax, because although there is only 1 user object, it is structured in the json as an array ( note the [ ] , same for Email).
Here is a fiddle: http://jsfiddle.net/Lvc0u55v/5593/
UPDATE: For showing only the last email which is true, use ng-if:
<span ng-repeat="email in collection.user[0].Email| filter: {IsPreffered : true} " ng-if="$last"> {{email.Id}}</span>
Here is the updated fiddle:
http://jsfiddle.net/Lvc0u55v/5594/
One way to do this is to use ngRepeat on the user Emails array with a filter to get only those Emails where "IsPreffered": true. The filter compares each object in the Emails array with the filter object (filterEmail). This filter object is defined in the controller - this way you will be able to change by demand or even set it dynamically.
var app = angular.module('app', []);
app.controller('ctrl', function($scope) {
$scope.collection = {
"user": {
"Name": "B. Balamanigandan",
"Email": [{
"Id": "bala#gmail.com",
"IsPreffered": true
}, {
"Id": "mani#gmail.com",
"IsPreffered": false
}]
}
};
$scope.filterEmail = {
"IsPreffered": true
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app" ng-controller="ctrl">
<div>
<h3>Employee Details:</h3>
<span> {{collection.user.Name}} </span>
<span ng-repeat="email in collection.user.Email | filter : filterEmail ">
{{email.Id}}
</span>
</div>
</body>
NOTE: To my understanding it doesn't make much sense to have user as an array inside an object (in my example I removed the inner array). If you insist on keeping this data-schema, you will need to change every reference of collection.user to collection.user[0].
I am trying to set up an example in which a series of news items will be passed in using ajax in a json format. At the moment I am just using a function to simulate returned data.
Here is the jsfiddle: http://jsfiddle.net/c8b4naL5/
<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>
<span data-bind="foreach: { data: newsItems, as: 'item' }" >
<!-- <span data-bind="foreach: { data: items, as: 'item' }"> -->
<div class="news-item">
<span data-bind='text:item.title'></span>
</div>
</span>
<script type="text/javascript">
function NewsItemsCall(){
return {
newsItemsFromCall: [
{title:'First Title From call'},
{title:'Second Title From call'}
]
}
}
function NewsItem(newsItemsCall){
var map = ko.mapping.fromJS(newsItemsCall);
return map;
}
var viewModel = {
newsItems:ko.observableArray([new NewsItem(new NewsItemsCall())])
}
ko.applyBindings(viewModel);
</script>
The ko.toJSON displays the following:
{
"newsItems": [
{
"newsItemsFromCall": [
{
"title": "First Title From call"
},
{
"title": "Second Title From call"
}
],
"__ko_mapping__": {
"ignore": [],
"include": [
"_destroy"
],
"copy": [],
"observe": [],
"mappedProperties": {
"newsItemsFromCall[0].title": true,
"newsItemsFromCall[1].title": true,
"newsItemsFromCall": true
},
"copiedProperties": {}
}
}
]
}
At this point I am just trying to get it to work to display the data in the template. Any insights would be appreciated. Thanks in advance.
Well the modification required could be approached from either the data side or the client side. At face value, your view isn't matched up to the data due to newsItems containing an array of newItemsFromCall. If the data is in the correct format, then just add another foreach binding.
Modifying the data
NewsItemsCall could return an array instead of an object
be aware of the return of the mapping call depending on how you will be using that value elsewhere
Modifying the UI
<span data-bind="foreach: { data: newsItems, as: 'item' }" >
<div data-bind='foreach: item.newsItemsFromCall'>
<span data-bind='text: title'></span>
</div>
</span>
Modified fiddle with changes to the data structure. I also included an alternate approach that maps the fromJS call directly as a viewmodel.
Example of mocking json calls in a fiddle.
I'm new to Ember.js and I'm trying to get my head around it.
I have the following code (http://jsfiddle.net/6wPmW/ for a working example):
<script type="text/x-handlebars">
<div id="ViewAddresses" class="location_search_results selected_searches clearfix">
<div>
<div>
{{#each MapSearch.ViewAddressesC}}
<div class="row">ghfdg</div>
{{/each}}
</div>
</div>
</div>
</script>
JS:
MapSearch = Ember.Application.create();
MapSearch.ListAddress = Ember.Object.extend({
list_info: null,
node_level: null,
node_value: null,
removed_properties: null
});
MapSearch.ViewAddressListC = Ember.ArrayController.create({
content: [],
initialize: function() {
me = this;
var l = MapSearch.ListAddress.create({
node_level: "test",
node_value: "test"
});
me.pushObject(l);
var l = MapSearch.ListAddress.create({
node_level: "test",
node_value: "test"
});
me.pushObject(l);
console.log(me);
}
});
MapSearch.ViewAddressListC.initialize();
console.log(MapSearch.ViewAddressListC.get("content"));
Surely I should get two <divs> created from the each loop?
The error is in your template:
{{#each MapSearch.ViewAddressesC}}
should be
{{#each MapSearch.ViewAddressListC}}
See this JSFiddle.