I am trying to work with handlebar templates, but it's not going so well.
In *.html.twig I have:
<script id="entry-template" type="text/x-handlebars-template">
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
</div>
</script>
<span id="demo">
</span>
<script>
var source = document.getElementById("entry-template").innerHTML;
var template = Handlebars.compile(source);
var context = {title: "My New Post", body: "This is my first post!"};
var html = template(context);
document.getElementById("demo").innerHTML = html;
</script>
And there is an error:
Variable "title" does not exist.
When I put this code in simple index.html w/o Symfony etc. it works. Any ideas how to fix it?
This is happening because Twig is also an HTML templating language which also uses {{ ... }} syntax to denote variables, just like Mustache is, so Twig is trying to parse it before outputting the HTML.
If you want to use Twig and Mustache together, then you'll need to escape/double-encode the curly braces that are intended for Mustache so that Twig doesn't try to parse them first.
There is a repo on Github which lets you define your own custom delimiters for Handlebar templates.
Related
I'm using the underscore library to populate my template.
It works like a charm when my variable day is inside a tag. like this snippet from my code:
<template>
<label>Schedule</label>
<select class="form-control" onchange="set_from_hour('<%=day%>')" name="some_name" id="<%=day%>from_hour" >
<option value=0 selected='selected'>00</option>
<option value=1>01</option>
...
</template>
to populate this template I use this function:
days_schedule = ['monday','tuesday','wednesday','thursday','friday','saturday','sunday']
function show_schedule_week(){
_.each(days_schedule,function(day){
_.templateSettings.variable = 'day'
var template = _.template($('template').html())
console.log(day+'_schedule')
$('#'+day+'_schedule').prepend(template(day))
})
}
Now the problem comes when i want my HTML code to display the variables, say in a header tag the variable day like below:
<template>
<h1> <%- day%> </h1>
</template>
The browser displays
<%- day%>
instead of the value of the variable.
Do you know what I'm doing wrong?
The problem is with the string that you pass to _.template(): the HTML that you read from the DOM does not have <%- day%>, but <%- day>. This is because < has a special meaning in HTML, and as here it does not represent a tag, it is encoded with an HTML entity. The same goes for >.
There are several solutions to this. One is to not use a template element in your HTML, but a string literal in your code. If however you prefer to stick with the template element (which is reasonable), then you could turn the template content into an HTML comment.
Here is an example:
days_schedule = ['monday','tuesday','wednesday','thursday','friday','saturday','sunday']
function show_schedule_week() {
_.each(days_schedule,function(day){
_.templateSettings.variable = 'day'
// unwrap the template content by removing the HTML comment tag start/end
var template = _.template($('template').html().slice(4, -3));
$('#'+day+'_schedule').prepend(template(day))
})
}
show_schedule_week();
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.11.0/underscore-min.js" integrity="sha512-wBiNJt1JXeA/ra9F8K2jyO4Bnxr0dRPsy7JaMqSlxqTjUGHe1Z+Fm5HMjCWqkIYvp/oCbdJEivZ5pLvAtK0csQ==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.js"></script>
<template><!--
<h3> <%- day%></h3>
--></template>
<div id="monday_schedule"></div>
I want to use handlebars to display a series of data in an unordered list, split between "title" and "articles." However, some of the articles will contain different HTML tags, be it <a> tags for link. If you take a look at my code below, when the data is appended to the DOM, rather than showing a link like 'You can read more about it here', it says the actual HTML anchor tags. Does anyone know a way around this?
<div id="myDiv"></div>
Consider the following template:
<script id="my-template" type="text/x-handlebars-template">
<div style='margin: 20px'>
<ul style='list-style-type: none; width:500px'>
<h4 style='padding:10px; overflow: auto'>General Credit</h4>
{{#each this}}
<li style='padding:10px; overflow: auto'>
<h3>{{title}}</h3>
<p>{{article}}</p>
</li>
{{/each}}
</ul>
</div>
</script>
My javascript looks like this:
//Data for Articles
var articleData = [
{
title: "My title here",
article: "You can learn more about it <a href='https://www.google.com'>here</a>"
}
];
//Get Template From Script Tag
var source1 = $("#my-template").html();
//Compile Template
var template1 = Handlebars.compile(source1);
$("#myDiv").append(template1(articleData));
You should use triple curly braces:
<li style='padding:10px; overflow: auto'>
<h3>{{{title}}}</h3>
<p>{{{article}}}</p>
</li>
So that handlebars doesn't escape the HTML code within your string.
Here the reference.
Cheers
You can use triple brackets to escape html.
Try {{{article}}}
Simple you {} {} helper call is a simple identifier, followed by zero or more parameters (separated by space). Each parameter is a Handlebars expression.
{{{link story}}}
In this case, link is the name of a Handlebars helper, and story is a parameter to the helper. Handlebars evaluates parameters in exactly the same way described above in "Basic Usage".
Reread the documentation more carefully. Simply put {{{}}} instead of {{}} around the article in my template, and the HTML tags render fine now.
Handlebars documentation: http://handlebarsjs.com/expressions.html
I am in beginning of a web project and I want to read my web site stings such as labels, title of pages, placeholder and ... from a json file. i think this approach may help me to increase my speed in changes and create a multi language web site.
is there any jquery library for doing this? and if ther is not how can i do this work by jquery?
You can make mustache templates and populate them with data using handlebars.js:
http://handlebarsjs.com/
Mustache templates use curly braces as placeholders and handlebars uses the json format to hold the data. It could look something like this (though not a full working example):
HTML:
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
</div>
Javascript:
var context = {title: "My New Post", body: "This is my first post!"};
var html = template(context);
Result:
<div class="entry">
<h1>My New Post</h1>
<div class="body">
This is my first post!
</div>
</div>
Here is a working example: https://jsfiddle.net/k4u64exL/
What you're searching for is a Javascript/jQuery Template Engine - there are lot of them (start e.g. with http://www.sitepoint.com/10-javascript-jquery-templates-engines/ ).
If you want to write your own template engine try the following:
1) Fetch JSON-Data with Ajax
2) Fetch Template with Ajax
3) Apply variables from JSON-File to Template File (simple replace)
4) Append the result to the current page.
I just started using Mustache and I like it so far, but this has me perplexed.
I am using the GitHub gist API to pull down my gists, and part of what I want to do is include the embedding functionality into my page. The problem is Mustache seems to not want to have anything to do with my dynamic script tag.
For example, this works fine:
<div class="gist-detail">
{{id}} <!-- This produces a valid Gist ID -->
</div>
Additionally, this works perfect:
<div class="gist-detail">
<script src='http://gist.github.com/1.js'></script> <!-- Produces the correct embed markup with Gist ID #1 -->
</div>
If I try to pull these together, something goes terribly wrong:
<div class="gist-detail">
<script src='http://gist.github.com/{{id}}.js'></script> <!-- Blows up! -->
</div>
Chrome Inspector shows this:
GET https://gist.github.com/%7B%7Bid%7D%7D.js 404 (Not Found)
... which looks like to me something is weird with escapes or whatnot, so I switch over to the raw syntax:
<div class="gist-detail">
<script src='http://gist.github.com/{{{id}}}.js'></script> <!-- Blows again! -->
</div>
And I get the same result in Inspector:
GET https://gist.github.com/%7B%7B%7Bid%7D%7D%7D.js 404 (Not Found)
How do I get the correct values to embed in the script tag?
EDIT
I am injecting the template as follows (in document.ready:
function LoadGists() {
var gistApi = "https://api.github.com/users/<myuser>/gists";
$.getJSON(gistApi, function (data) {
var html, template;
template = $('#mustache_gist').html();
html = Mustache.to_html(template, {gists: data}).replace(/^\s*/mg, '');
$('.gist').html(html);
});
}
The actually template is inside of a ruby partial, but it is wrapped in a div (not a script tag, is that a problem?) (that's hidden):
<div id="mustache_gist" style="display: none;">
{{#gists}}
<!-- see above -->
{{/gists}}
</div>
I assume a div is ok rather than a script because in either case, I'm pulling the .html(). Is this a bad assumption?
To avoid automatic escaping in Mustache use {{{token}}} instead of {{token}}.
It seems like your template is in HTML and trying to retrieve the template using html() results in a pre-URL-escaped template to be returned. Try placing your template inside a <script type="text/html"> tag instead.
When you embed your template inside an HTML element that excepts more HTML elements as children, it may get processed by the browser as HTML. Escaping may occur. By using a <script> tag with a non-script content type, you're basically telling the browser not to touch your template.
It looks like your script is getting requested before Mustache has a chance to update the src property. What you want to do is define the template in a way that it's not parsed as part of the DOM. A common approach is to define your template inside of a <textarea> tag. This will preserve formatting and prevent character escaping.
<textarea id="gist-detail-template" style="display:none">
<script src='http://gist.github.com/{{id}}.js'></script>
</textarea>
Now, to instantiate the template:
var template = $('#gist-detail-template').val();
var html = Mustache.to_html(template, yourTemplateData);
Here's an official example: http://mustache.github.com/#demo
this is my html:
<script type="text/html" id="ul-template">
<ul id="list">
{{> li-templ}}
</ul>
</script>
<script type="text/html" id="ul-template2">
<div id="list2">
{{> li-templ}}
</div>
</script>
<script type="text/html" id="li-templ">
<p>{{ name }}</p>
</script>
as you can see, I want to reuse the #li-templ part, but it seems that I have to write it into a file called li-templ.mustache then I can include it as partial?
can I just define them in the single html file?
I'm assuming you're using the JS flavor of Mustache.
In mustache.js an object of partials may be passed as the third argument to Mustache.render. The object should be keyed by the name of the partial, and its value should be the partial text.
You need to:
Define some dummy data for name
Get your partial template by getting the HTML of #li-templ
Create an object with the name of the partial (li-templ) as the key
Tell Mustache to render each template with the view data including your partial
Here's some jQuery to do just that:
var view = {"name" : "You"},
li = $('#li-templ').html(),
partials = {"li-templ": li},
ul1 = Mustache.to_html($('#ul-template').html(), view, partials),
ul2 = Mustache.to_html($('#ul-template2').html(), view, partials);;
document.write(ul1, ul2);
Here's a jsFiddle of it all working- http://jsfiddle.net/maxbeatty/EYDfP/
ICanHaz.js (ICH) can help you with this.
ICanHaz.js: A simple/powerful approach for doing client-side templating with Mustache.js.
I've found that mixing templates (in scripts tags) with the ordinary HTML in the page messes with my code editor (syntax highlighting, indenting etcetera). Loading them as a separate server keeps your HTML clean.
Check out this ICH pull request for automatic loading of <script type="text/html" src="my-templates.html"></script> from your server to one template per file.
You could also load more than one template per remote HTML file this using simple code like:
function getTemplates(url) {
$.get(url, function (response) {
$('template', response).each(function () {
ich.addTemplate(this.id, $(this).text());
});
});
}
Or, if you'd like ICH to load them automatically from urls in your page:
<head>
<link rel="templates" type="text/html" href="my-templates.html">
</head>
$("link[type=templates]").each(function (index, link) {
getTemplates(link.attr("href"));
});
In your my-templates.html
<templates>
<template id="ul-template">
<ul id="list">
{{> li-templ}}
</ul>
</template>
<template id="ul-template2">
<div id="list2">
{{> li-templ}}
</div>
</template>
<template id="li-templ">
<p>{{ name }}</p>
</template>
</templates>