I'm planning to use backbone.js and underscore.js for creating website, and I will have lots of underscore templates:
<script type="text/template" id="search_template">
<p id="header">
//header content will go here
</p>
<p id="form">
<label>Search</label>
<input type="text" id="search_input" />
<input type="button" id="search_button" value="Search" />
</p>
<p id="dynamic_date">
//dynamic data will be displayed here
</p>
</script>
Of course my templates will be much more plicated.
Since I will have lots of them, I don't want to load all templates every time when page loads. I want to find a solution, where I can load specific template only when it will be used.
Another thing is that most of my templates will have same structure, only <p id="form"></p>
and <p id="dynamic_date"></p>
content will differ.
Could you please suggest me how should I do it?
Thanks,
I'm planning to use backbone.js and underscore.js for creating website, and I will have lots of underscore templates:
<script type="text/template" id="search_template">
<p id="header">
//header content will go here
</p>
<p id="form">
<label>Search</label>
<input type="text" id="search_input" />
<input type="button" id="search_button" value="Search" />
</p>
<p id="dynamic_date">
//dynamic data will be displayed here
</p>
</script>
Of course my templates will be much more plicated.
Since I will have lots of them, I don't want to load all templates every time when page loads. I want to find a solution, where I can load specific template only when it will be used.
Another thing is that most of my templates will have same structure, only <p id="form"></p>
and <p id="dynamic_date"></p>
content will differ.
Could you please suggest me how should I do it?
Thanks,
Share Improve this question edited Jan 12, 2015 at 20:56 Ken Redler 23.9k8 gold badges59 silver badges69 bronze badges asked Sep 24, 2011 at 21:36 kahakaha 1,4172 gold badges17 silver badges21 bronze badges3 Answers
Reset to default 8Edit: I did some research and ported my iCanHaz code to underscore it also uses localStorage is available
Here is a github repository: https://github./Gazler/Underscore-Template-Loader
The code is:
(function() {
var templateLoader = {
templateVersion: "0.0.1",
templates: {},
loadRemoteTemplate: function(templateName, filename, callback) {
if (!this.templates[templateName]) {
var self = this;
jQuery.get(filename, function(data) {
self.addTemplate(templateName, data);
self.saveLocalTemplates();
callback(data);
});
}
else {
callback(this.templates[templateName]);
}
},
addTemplate: function(templateName, data) {
this.templates[templateName] = data;
},
localStorageAvailable: function() {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch (e) {
return false;
}
},
saveLocalTemplates: function() {
if (this.localStorageAvailable) {
localStorage.setItem("templates", JSON.stringify(this.templates));
localStorage.setItem("templateVersion", this.templateVersion);
}
},
loadLocalTemplates: function() {
if (this.localStorageAvailable) {
var templateVersion = localStorage.getItem("templateVersion");
if (templateVersion && templateVersion == this.templateVersion) {
var templates = localStorage.getItem("templates");
if (templates) {
templates = JSON.parse(templates);
for (var x in templates) {
if (!this.templates[x]) {
this.addTemplate(x, templates[x]);
}
}
}
}
else {
localStorage.removeItem("templates");
localStorage.removeItem("templateVersion");
}
}
}
};
templateLoader.loadLocalTemplates();
window.templateLoader = templateLoader;
})();
Calling it would look something like:
templateLoader.loadRemoteTemplate("test_template", "templates/test_template.txt", function(data) {
var piled = _.template(data);
$('#content').html(piled({name : 'world'}));
});
Here is my original answer
Here is a method I wrote for ICanHaz (mustache) that performs this exact function for the same reason.
window.ich.loadRemoteTemplate = function(name, callback) {
if (!ich.templates[name+"_template"]) {
jQuery.get("templates/"+name+".mustache", function(data) {
window.ich.addTemplate(name+"_template", data);
callback();
});
}
else {
callback();
}
}
I then call it like so:
ich.loadRemoteTemplate(page+'_page', function() {
$('#'+page+'_page').html(ich[page+'_page_template']({}, true));
});
I really like the way the stackoverflow team has done templating with the mvc-miniprofiler. Take a look at these links:
Includes.js (Github link)
Includes.tmpl (Github link)
They use the local storage to cache the templates locally if your browser supports local storage. If not they just load it every time. Its a pretty slick way to handle the templates. This also allows you to keep your templates that aren't required immediately in a separate file and not clutter up your html.
Good luck.
Although both of the above answers work, I found the following to be a much simpler approach.
Places your templates wrapped in script tags into a file (say "templates.html") as follows:
<script type="text/template" id="template-1">
<%- text %>
</script>
<script type="text/template" id="template-2">
oh hai!
</script>
Then the following bit of javascript:
$(document).ready(function() {
url ='http://some.domain/templates.html'
templatesLoadedPromise = $.get(url).then(function(data) {
$('body').append(data)
console.log("Async loading of templates plete");
}).fail(function() {
console.log("ERROR: Could not load base templates");
});
});
Which then let's you select your templates quite simply using the IDs you previously defined. I added the promise
$.when(templatesLoadedPromise).then(function() {
_.template($('#template-1').html(), {'text':'hello world'} )
});
You can then extend this and load multiple files if you want.
As a side note, I've found that any core templates needed for initial page render are better embedded in the HTML (I use tornado modules on the server) but that the above approach works very nicely for any templates needed later (e.g., in my case the templates for a registration widget which I want to use across pages is perfect for this as it'll only be loaded on user interaction and is non-core to the page)