When working with Mustache, or any templating engine, a properly structured JSON object is needed to render some specific template. Generally (I believe), a developer knows their application's data model, and how they want to show data in a template, but find that their data model doesn't perfectly output JSON in the form their templates expect. So we often need to write data processing functions that transform data model outputs into acceptable mustache template inputs.
For example, #Liang's application outputs a JSON array like:
"prop":{"brands":["nike","adidas","puma"]}
but his template expects it to be in the form:
"brands":[{"name":"nike"},{"name":"adidas"},{"name":"puma"}]
so he needs to transform it via:
var data = {brands: obj.prop['brands'].map(function(x){ return {name: x}; })};
Liang also could have tweaked his template to get it working without a data transformation step. But what if I don't know what the template is before hand and my only template guarantee is that its tags resolve to keys in my data model. Is it possible to write a function bridge(data_model, template) which takes as input the data model and mustache template and outputs the transformation function Transform. Such that Transform itself is the code which massages the data model outputs into acceptable mustache template inputs.
Said another way, if
data_model = "prop":{"brands":["nike","adidas","puma"]}
and
template = {{#brands}}
<b>{{name}}</b>
{{/brands}}
then what bridge produces the javascript
{brands: obj.prop['brands'].map(function(x){ return {name: x}; })} = bridge(data_model, template)
(the output of bridge would be javascript code).
I understand that this may be too unconstrained to give a good answer, but I think everyone can recognize that at a minimum, bridge would need to be able to output nested for loops or map commands. How could I go about making perhaps a crude version of bridge that has for loop commands in the right places respective to mustache tags?.. sorry if this doesn't make great sense, it's a challenging question for me to articulate. Honestly, it feels a bit like asking for magic.
It isn't in javascript but R3M (written in php) can template json files as well. it syntax is borrowed from Smarty but different. it will reach production stability in 2023. It enables templates which can be used in .js, .json & .tpl.
{
"books": "{json.select($url, 'book')}"
}
see https://github.com/like-it/r3m-framework
Related
Basically, if you have a purely JS app (that get info from socket.io, or from a server with ajax request), and you need to show this data after processing it, what technique are you using?
Currently i'm creating the elements manually with code like
var myDiv = new Element('div',{ /* options */);
And injecting it where I need making all the DOM structure. I find this hard to maintain and especially for those designers that can code html, but they can't code html from JS.
Is there any way that will improve this process? Is it better to get the html from ajax? or just make html code in a string?
I'm looking for the most optimal in terms of maintenance and resources.
What you're looking for is a "template".
You have an HTML template (some divs, etc) and you bind this with the datas you provide in JS. Then, with whatever template engine you're using, you can get the full HTML.
Here are some template engines out there:
https://github.com/flatiron/plates
http://embeddedjs.com/
And a code sample using plates:
var Plates = require('plates'); // specific to node.js, see for client-side use
var html = '<div id="test">Old Value</div>';
var data = { "test": "New Value" };
var output = Plates.bind(html, data);
console.log( output ); // '<div id="test">New Value</div>'
You can store your templates either in a single file ("templates.html") loaded through ajax, or by storing it in the HTML page (not really recommended for maintenance matters).
If you store them all in an external file, you can do something like this:
templates.html:
<!-- text/html isn't parsed by the browser so we can put anything in it -->
<script type="text/html" id="template1">
<!-- put your template in there
</script>
And you can get its content through getElementById( 'template1' ).
Easiest way for you if project is in late stage to add something like jQuery.template plugin and create templates in separate files. Then, use backend to combine those peaces in single page and on DOM Ready fire up your client side app.
If your project is in early stage use AngularJs or BackboneJS frameworks. Believe me it is worth every cent :)
I would recommend you take a look at Backbone.js.
Backbone.js gives structure to web applications by providing models
with key-value binding and custom events, collections with a rich API
of enumerable functions, views with declarative event handling, and
connects it all to your existing API over a RESTful JSON interface
I use backbone even if I am not over a RESTful interface. It's pretty easy to separate the structure from the behavior ... You can achieve the same using jQuery but it wont be as neat and clean. It's one of the MV* framework. You have:
Models containing the interactive data as well as a large part of the logic surrounding it: conversions, validations, computed properties, and access control.
Collections are ordered sets of models.
Views: The general idea is to organize your interface into logical views, backed by models, each of which can be updated independently when the model changes, without having to redraw the page
Routers provides methods for routing client-side pages, and connecting them to actions and events
It's getting attention recently. Apps that were created using Backbone include:
FourSquare
LinkedIn for Mobile
This is a great resource if you're starting to work with Backbone.
Distal Templates http://code.google.com/p/distal/ :
<table id="a">
<tr><th>OPINIONS</th></tr>
<tr data-qrepeat="m keywords"><td data-qtext="m.name"></td></tr>
</table>
Then call:
distal(document.getElementById("a"), {
keywords: [
{name:"Brilliant"}, {name:"Masterpiece"}, {name:"Witty"}
]
});
will become:
<table>
<tr><th>OPINIONS</th></tr>
<tr><td>Brilliant</td></tr>
<tr><td>Masterpiece</td></tr>
<tr><td>Witty</td></tr>
</table>
And injecting it where I need making all the DOM structure. I find this hard to maintain and especially for those designers that can code html, but they can't code html from JS.
Another option is modest. As you can see from the documentation, it obviates the need for HTML chunks in javascript. The designers can change the HTML structure without needing to look at the javascript, and javascript coders can use parameters defined by the designers to fill in the data (all in javascript).
This example is from the readme:
HTML:
<div>
<contact>
<name>Casey Jones</name>
<phone>123-456-7890</phone>
</contact>
</div>
Javascript:
var contact = {
name : "Casey Jones",
cell : "123-456-7890"
};
var out = modest.render('contact',contact);
Recently I became interested of the jQuery template engine.
For the ajax call is very performant, because the data exchange is less.
But when I load my application the first time, I use only php and html for print the data, so for use this technic do I have to duplicate the template? One for php html and one for javascript?
How could I resolve this problem?
It is possible to use the same templates on the server side and the client. For example, mustache has implementations in several languages including PHP and Javascript. But generally I find it's easier to stick to one approach.
If you're using jQuery templating to render on the client anyway, why not render in Javascript the first time as well. To avoid needing an extra AJAX call, you can inject your data model into the page as a javascript object and pass that into the template renderer.
Here's an example. The json_encode function should be useful for this.
<script type="text/javascript">
// This line gets generated by your PHP code.
// You'll want to use the JSON methods instead of generating it by hand.
var myModel = { name: 'Fred', surname: 'Bloggs' };
$(document).ready(function() {
// Here you render the template using the data that's
// already in myModel
});
</script>
You could try Distal templating engine.
Your HTML page serves as part of the template.
<div>
Hi, <span data-qtext="user.name">Guest</span>
</div>
When you first load it displays "Hi, Guest" then you run the template and you can substitute for "Guest".
Update: after another day of digging
into this issue, I have found that the
current jQuery template lib provides
no way to do this. this article
describes a good approach.
I would still like to hear of any
additional thoughts on doing this. The
article linked above requires that the
returned string of templates be
inserted into the DOM. Seems as though
leaving the DOM out of this would be
ideal, and less overhead on the
browser. Imagine a large page, with
multiple composite templates that may
not get used. Although, maybe because
the templates are wrapped in a script
tag, there is only a single DOM item per template? Come on, let's
hear some thoughts...
Using jQuery template libs, what's the best way to combine multiple, related, relatively small templates together? Do you need a single <script> tag for each individual template? What about in the case of dynamically pulling these templates via AJAX? Can I combine these templates somehow?
Consider the following:
<script id="movieTemplate" type="text/x-jquery-tmpl">
{{tmpl "#titleTemplate"}}
<tr class="detail"><td>Director: ${Director}</td></tr>
</script>
<script id="titleTemplate" type="text/x-jquery-tmpl">
<tr class="title"><td>${Name}</td></tr>
</script>
Now because these two templates are very closely related (and one depends on the other) it would make sense to consolidate these into a single AJAX call, and get them both at once. I have a few ideas, but I'd like to know if there is common/best way to do this? Currently I pull in a chunk of HTML, and then do a .find() to get the specific peice of HTML for a template... e.g.:
var templatePackage = fancyAjaxCalltoGetTemplates();
"templatePackage" might then look like this:
<div id="templatePkg">
<div id="movieTemplate">
{{tmpl "#titleTemplate"}}
<tr class="detail"><td>Director: ${Director}</td></tr>
</div>
<div id="titleTemplate">
<tr class="title"><td>${Name}</td></tr>
</div>
</div>
I could then do:
var titleTemplate = jQuery.template('titleTemplate', $(templatePackage).find('#titleTemplate') );
and
var movieTemplate = jQuery.template('movieTemplate', $(templatePackage).find('#movieTemplate') );
...let me know what you think... what would you do?
I like the referenced article in your update, except the assumption that you can't cache templates unless you insert them into the DOM. From the jQuery.tmpl documentation,
"To cache the template when using markup that is obtained from a string (rather than from inline markup in the page), use $.template( name, markup ) to create a named template for reuse. See jQuery.template()."
Using this, we can build a javascript template management system that allows us to load as many templates at a time as we need while keeping the DOM clean. On the client, keep a hash of template objects by name. You can use your favorite object based javascript pattern here, but I would think the structure could be like this:
templates[templateName] = {
templateMarkup: markupFromServer,
loadedAt: Date.now(),
compiledTemplateFunction: jQuery.template( templateName, markupFromServer )
}
Then use the templates to generate HTML like this:
templates['unique-name'].compiledTemplateFunction(inputData)
Then, build an unload mechanism to free up memory:
function unload(templateName) {
delete templates[templateName];
delete jquery.template[templateName];
}
Most importantly, you now have a method of storing multiple templates so you can make requests like: $.get('/TemplateManagement/Render', arrayOfTemplateNamesToLoad, loadManyTemplatesSuccess) to load multiple templates at a time. The only thing we need is a controller TemplateManagement that will take an array of template names as an input and return JSON that pairs a template name with its markup. There are a few ways to do this but it seems to me the most convenient is to define partial views for each template. In ASP.NET MVC 3, you can use this technique and RenderPartial to emit each template's markup into a JSON response. You can either name the partial views the same as the templates or map the names in some custom way.
OK, I read the article you reference in this post. As I see it, his way is probably one of the best ways to load up the template page(s). The only thing I don't like is the asynchronous problems that could crop up, esp. if you need to immediately do some templating before the async get returns... plus any binding issues that could happen before it returns something. In several projects I have done I use his "ancient" SSI (server side includes), but I just use something even easier like:
<% Response.WriteFile("this_page_template_file.html"); %>
You could put it anywhere where you'd place a tag. Like he says, just put in only the templates you need, or maybe include two templates: one is a "base" template with commonly-used items and the second one would have the page-specific ones with template references {{tmpl}}.
Is this even close to an answer? ;-)
[First off, great question. I love this topic]
I have no experience with the plugin "jquery-template-libs", but there is a particular lightweight javascript template plugins that are becoming almost a standard and plays very nicely with jQuery, which is probably better suited for the task than JTL, Mustache:
https://github.com/janl/mustache.js
It's got something that's called a "partial" which is essentially a way to include smaller templates within another one. Which sounds like it will help you out a lot.
On top of that there is a library called ICanHaz.js:
http://icanhazjs.com/
ICanHaz essentially extends Mustache to include built in functionality for templates and works incredibly well.
Mustache/ICanHaz allow you to add templates by variable, by a json call or by using tags. The choice is yours.
I know this is an old question but you might want to take a look at Closure-Templates. They provide the kind of functionality you're after with the added advantage of being compiled into JavaScript at compile-time instead of at run-time in each user's browser.
If you do decide to look into using them then I'd suggest using plovr for building them.
I have a big chunk of deeply-nested semi-structured JSON and would like to generate HTML from it. At the moment I'm using jQote2, but much of the code inside my templates deals with dynamically finding the next template to render and then calling it. What's a single <xsl:apply-templates> in XSLT takes several lines with JavaScript and jQuote. I dearly miss the pattern matching capabilities of XSLT. Is there any (templating) library in JavaScript that allows me to dynamically decide from the data which template to render?
Here is an example of what I want. Suppose I have a JSON structure like this:
{
items:[
{foo:1, bar:2},
{foo:7, baz:99},
{foo:8, quux:3}
],
curdate:'2010-07-07'
}
I'd like to have a "root" template that renders the curdate field and then renders the items. If an item contains a "bar" field, I want the item to be rendered with a template named "tpl-bar" (or something like that), otherwise a template named "tpl-foo" should be used. Filtering capabilities (like "do not render items that have a quux field") would be a nice-to-have.
I am aware of the JSONT library, however from what I see it's not dynamic enough to accomplish what I described.
If no such library exists, I'm on the verge of giving it a shot myself. But I'm not sure how to do it at the moment. Code examples or general descriptions would help me.
There's also JSLT, from what I remember reading it's a little more advanced than JSONT. I've never actually used it, though. The problem is that these libraries aren't hugely popular and so not a lot of work gets done to improve them and build upon them.
On the plus side, it's open source so if you don't find a feature you want you could attempt to add it yourself.
First, 2 common (basic) approaches:
# returning from some FoosController method
respond_to do |format|
# 1. render the out a json representation
format.json { render :json => #foo }
# 2. render an RJS template, say update.js.erb
format.js { render }
end
# in update.js.erb
$('#foo').html("<%= escape_javascript(render(#foo)) %>")
These are obviously simple cases but I wanted to illustrate what I'm talking about. I believe that these are also the cases expected by the default responder in rails 3 (either the action-named default template or calling to_#{format} on the resource.)
The Issues
With 1, you have total flexibility on the view side with no worries about the template, but you have to manipulate the DOM directly via javascript. You lose access to helpers, partials, etc.
With 2, you have partials and helpers at your disposal, but you're tied to the one template (by default at least). All your views that make JS calls to FoosController use the same template, which isn't exactly flexible.
Three Other Approaches (none really satisfactory)
1.) Escape partials/helpers I need into javascript beforehand, then inserting them into the page after, using string replacement to tailor them to the results returned (subbing in name, id, etc).
2.) Put view logic in the templates. For example, looking for a particular DOM element and doing one thing if it exists, another if it does not.
3.) Put logic in the controller to render different templates. For example, in a polymorphic belongs to where update might be called for either comments/foo or posts/foo, rendering commnts/foos/update.js.erb versus posts/foos/update.js.erb.
I've used all of these (and probably others I'm not thinking of). Often in the same app, which leads to confusing code. Are there best practices for this sort of thing? It seems like a common enough use-case that you'd want to call controllers via Ajax actions from different views and expect different things to happen (without having to do tedious things like escaping and string-replacing partials and helpers client side).
Any thoughts?
The best practice is to have your Web UI use the RESTful API. That is, get and put resources in JSON format using JavaScript running in the client, just as a third party might get and put resources in JSON format using RestClient. That means you don't have .rjs or .js.erb templates on the server - you might instead have Mustache or Handlebars or jQuery templates, plus the glue JavaScript, embedded in (or statically linked to from) the HTML page originally delivered to the Web client.
Of course, the quick-and-dirty approach of using remote => true, and going to the server and rendering a JavaScript code template to produce JavaScript that will be executed on the client ... is easier. And it was fairly good practice for a while. But we need JavaScript for a data format now, and we have superior capabilities today for pulling data in JSON format and rendering templates within the client.
Not sure if this work for you, but I would do the following:
Generate .js templates using ERB, these templates will be static
The templates could be mustache, jaml, jQuery Templates or something else.
Use a rake task to generate all templates and create static .js files out of them.
Include these static files using , they will be cached by the browser.
Populate the templates with json data and include the generated html.
This assumes that the templates can in fact be static, which depends on the situation at hand. But generally this should work.