Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cache mustache templates?

I would like to cache mustache templates.

I know that I could include mustache templates directly, like this:

<script id="mustache-template" type="text/html">
<h1>{{title}}</h1>
</script>

And call those with javascript, like this:

var html, template, data;
data = {  
    title : "Some title"
}; 
template = document.getElementById('mustache-template').innerHTML;
html = Mustache.to_html(template, data);

This won't cache templates. Only way I could figure out is usage of link -tags, but how do I call template content via javascript without an ajax request?

This won't work (of course)...

HTML

<link type="text/html" href="/mustache/template.tpl" id="mustache-template" />

Javascript

document.getElementById('mustache-template').innerHTML;
like image 760
kaulusp Avatar asked Jun 09 '11 12:06

kaulusp


3 Answers

This question is very interesting! I had the same problem several months ago when I started to use mustache for 'huge' front-end templating within a rails project.

I ended up with the following solution...


Mustache templates are inside a public folder :

/public/templates/_template_name.tpl

Whenever I need a template I have this helper getTemplate that does some stuff (there's some mootools, but there are comments too):

// namespace.templatesCache is an object ( {} ) defined inside the main app js file

var 
    needXHR = false, // for callback function
    templateHTML = ""; //template html

if(!(templateHTML = namespace.templatesCache[template_name])){ //if template is not cached

    templateHTML = (this.helpers.supportLocalStorage) ? localStorage.getItem(template_name) : ""; //if browser supports local storage, check if I can retrieve it

    if(templateHTML === "" || templateHTML === null){ // if I don't have a template (usually, first time), retrieve it by ajax

      needXHR = true;  

      new Request.HTML({ //or jQuery's $.get( url /*, etc */ ) 

          url: namespace.URLS.BASE+"templates/_"+template_name+".tpl", // url of the template file

          onSuccess : function(t, e, html, js){

                namespace.templatesCache[template_name] = html; //cache it

                if(_this.helpers.supportLocalStorage){ //and store it inside local storage, if available
                  localStorage.setItem(template_name,html); 
                }

                //call callback      
          }
      }).get();

    }else{ //retrieved by localStorage, let's cache it

        namespace.templatesCache[template_name] = templateHTML;

    }

}

if(!needXHR){ // I retrieved template by cache/localstorage, not by Ajax

    //call callback    

}

and I call this helper in this way :

namespace.helpers.getTemplate('template_name', function( templateHTML ){
    // the callback function
});

You can notice that first time user needs the template, there's an asynch request (you could make a sync request if u don't want to wrap some other code inside the callback)

I hope it could help and I'd love to receive feedbacks/suggestions concerning this stuff :)

like image 66
stecb Avatar answered Nov 15 '22 19:11

stecb


You could try to load your template in an iframe that contains an HTML page(that will be cached) with all your script tags inside.

Then you can read them from the main page, or push them from the iframe to the parent window.

That is what I do when using pure.js templates

like image 1
Mic Avatar answered Nov 15 '22 17:11

Mic


What you say it will not work, of course, because the innerHTML attribute of the liknek element will not give you the contents of the link.

You can use Chevron to load external templates from links like so:

You add in you template a link to your template file:

<link href="path/to/template.mustache" rel="template" id="templateName"/>

Then, in you JS you can render your template like so:

$("#templateName").Chevron("render", {name: "Slim Shady"}, function(result){
    // do something with 'result'
    // 'result' will contain the result of rendering the template
    // (in this case 'result' will contain: My name is Slim Shady)
});

The docs of Chevron will give more examples

like image 1
Nicu Surdu Avatar answered Nov 15 '22 19:11

Nicu Surdu