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.
Related
I would like to ask your advice on our situation about dynamic/static loading components.
We're developing a "multi language teaching app" for Android/iOS. For UI text we use ng2-translate plugin (JSON files for each language). For the lesson content we use separate HTML files for each language. In the beginning the user selects a language to learn and then sees related lessons as a list (which comes from a JSON file too). Clicking a lesson loads the related HTML file and dynamically compiles directives/pipes in it (which makes it more interactive). By directives, I mean simple functions like showing a toast when user clicks a custom directive, like this: <example tooltip="explanation to show as a toast">An example sentence</example>. But maybe we can use more complex directives in the future.
Up to building the app, everything goes well in browser. But the AoT compiler does not support "dynamic loader components" in mobile devices, so we need to decide whether or not use this approach. And at that point I'm really confused. We may change our structure but I don't know which way is better.
As far as I can see, we have three options (if there are more, please enlighten me):
Stop using html files and convert each of them into a component with html templates (using AoT compiler (--prod mode)):
Be able to use directives/pipes
Gain interactivity
Gain performance (that's the main purpose of AoT, right? but what if I use hundreds of html pages/components? isn't it a bulky solution?)
Use hundreds of pre-compiled html pages for grammar lessons, stories, texts...
Load pure HTML files into an innerHTML of a loader component (using AoT compiler (--prod mode)):
Don't use directives/pipes
Loose interactivity (except being able to use simple HTML tags like p, strong, em, table etc. --if we count this as an interactive content)
Gain performance a bit (as we use AoT?)
Load HTML files dynamically as components via one dynamic template component (using JiT compiler (--dev mode)):
Be able to use directives/pipes
Use separate html files
Gain interactivity
Loose performance
Do something that Angular generally does not recommend
I can't decide what to do now, if I want more interactivity, I should drop the performance that Angular proposes.
I just wanted to be able to handle these grammar lessons in a simple syntax (like HTML) as seperate files and not to use/declare components for each of them...
What would you recommend?
I asked same question to Ionic forum and I decided to implement the solution of a user that replied to me:
I went through this with Markdown, tried a bunch of things, and here's what I eventually settled on:
Store your objects however is convenient for you. In my case, that's markdown source.
Define two components; we'll call them skeleton and bone for now.
skeleton has an input property giving it the source. In ngOnChanges, you need to parse that source into an array of elements, each corresponding to a different type of bone.
skeleton's template looks something like this:
<template ngFor let-bone [ngForOf]="bones">
<app-bone [bone]="bone"></app-bone>
</template>
Make sure each bone has a discriminator indicating its type, and then the BoneComponent template is a big giant switch:
<blockquote *ngIf="bone.tag === 'blockquote'">
<app-bone *ngFor="let child of bone.children" [bone]="child"></app-bone>
</blockquote>
<br *ngIf="bone.tag === 'br'">
... every other block-level element we support...
Note that this can work recursively if you need it to, in that the
inside of the blockquote case is effectively another skeleton. I'm
using HTML elements here, but the general technique works equally well
for other user-defined components (as types of bones).
I am trying to figure out how to develop a multi-lingual website. My background in HTML, JS, CSS is not that broad (I have started only a week ago), therefore my understanding of this may not be the best.
For our example we will be creating three language mutations:
English (main one)
Spanish
French.
Here is what I have come across when I started searching for this under uncle Google.
The longest solution I can imagine: Create three folders named en, es, fr. These will contain the replica of the original webpage (e.g. index.html), but will be translated to respective language. Then on the top panel, you will have a button which upon clicking it will redirect used to a different folder (link is hard coded here). This solution is feasible if we are dealing with very small websites (with a few pages).
Second option I have found, was using WordPress plugins (found quite a few of those). Unfortunately, this solution is not viable, as I am not using wordpress to create a website.
Next option (which I believe would be the best), is to have one page for all language mutations, but instead of real text, you would insert some attribute with the key, which will determine what phrase should be inserted here. It could look like data-toTranslate('sTitle') (making this up). The question now would be, where would you store your texts? One option would be into a database, but I have not worked with them (under websites), therefore I would prefer something like a text file / csv file / or something like this. The problem I have with this solution (except the fact that I don't know how to do it yet :) ) is that I am not quite sure how website would react to this in terms of loading time. Maybe this is the best solution for a developer, yet the worst for the website?
Any comments, links or suggestions which would point me in the right direction would be more than welcome!
EDIT: as this question may seem too broad, I will try to trim it a bit down.
As I believe the option number three would be the best, then I would like to know the following things:
1) What do I need to create when I want to store simple key - value pairs (such as in this translation)? If I were in C#, I would e.g. create either simple XML or CSV file and I would parse it during runtime.
2) Can I achieve this with a simple JavaScript, or do I need to create some specific controllers / directives with AngularJS?
Create the english version of the website statically, as this is the main language. You should have a separate ID for every text element (and don't use obe word ids such as "a" "b" etc., so you can easily fibd them later.
Have a file on your server (text file works too) with the ids of fhe text tags, and the text in a format like
welcome-text | ["Welcome to the website" in Spanish]
-------------
Etc...
(Note: yoh need to store the translated sentences, but I don't know Spanish nor France)
Name your file to something like Spanish.txt.
When the page loads, download this file with javascript trough AJAX (this is where the static english version kicks in as a fallback), loop trough the text file and set the texts to the translated version.
You can of course use PHP with MysQL too, but I thought it is a bit overkill for 2 languages.
And yes, this can be done with 100% pure javascript, not even JQuery is required.
I normally using PHP to handle this multilingual. When every moment user view the website, it will set the default language to ENG. But, when the user select other language as the website display language, the website will reload and the PHP code will call the respective language folder to display all the selected language on the website. So, I think you should having few language folder, then dynamic calling each of the folder to get the keywords words and display it.
Often I find myself creating some partial views for a webpage which can be populated by some set of data e and subsequently attached to a given element attachable like so:
function mySection(e, attachable){
this.$mySection = $('<section>',{
class:'mySection'
});
$('<span>',{
text:e.someRelevantInformation
}).appendTo(this.$mySection);
this.$mySection.appendTo(attachable);
}
and then call the function:
mySection(someJSON, $(' body '));
Usually these sort of partial views have several categories or subsections, and sometimes even have nested partial views within them. Using JQuery like this is infinitely more scalable than doing something like
document.findElementById('mySection').append('<section><span>'+e.someText+'</span></section>');
or something of the sort. So are there any frameworks or technologies or even just personal techniques that take this even further? Ideally I would like something as seamless as Rails' .erb files, but I'm looking for an extension to Javascript, not HTML.
Edit
I should clarify that it's important to be able to dynamically generate these one after another, resulting in, in some cases, dozens of sections based on templates.
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 currently am working on a little app that requests user info from my server and displays them using a special template.
At first, I just hardcoded the little snippet in jQuery:
$("<li><div class='outer'><table><tr><td rowspan=2 class='imgcontainer'><img class='thumb'/></td><td><span class='username'/></td></tr><tr><td><span class='name'/></td></tr></table></div></li>")
I clone it several times.
It's ugly and I want it to have syntax highlighting and whatnot, so it would be better for me to have it in the HTML file itself.
Also, it will make merges easier so somebody can just change a line or two.
Is there a pattern for this? Am I OK putting it in the HTML file that I include this JS in (there's only one), and making it hidden using CSS.
The third option I thought of is just creating a separate HTML file and having jQuery request that from the server to keep it separate. Is this technique used much?
Also, is there any term I can use to describe what I'm doing? (It's harder to ask a question for a concept I don't know the name for)
I gave a similar answer on SO earlier today. What you are looking for is called micro-templates. John Resig posted this on his blog. Essentially you can get a json dataset and apply a template to the data to create html and update the DOM.