JavaScriptMVC's views are really just client side templates. Client side templates take data and return a string. Typically, the strings are HTML intended to be inserted into the DOM.
$.View is a templating interface that takes care of complexities using templates:
- Convenient and uniform syntax
- Template loading from html elements or external files
- Synchronous or asynchronous template loading
- Template preloading
- Caching of processed templates
- Bundling of processed templates in production builds
- $.Deferred support
JavaScriptMVC comes pre-packaged with 4 different template engines:
- EJS
- JAML
- Micro
- Tmpl
This tutorial uses EJS templates, but all the following techniques will work with any template engine with minor syntax differences.
When using views, you almost always want to insert the results of a rendered template into the page. jQuery.View overwrites the jQuery modifiers so using a view is as easy as:
$("#foo").html('mytemplate.ejs',{message: 'hello world'})
This code:
-
Loads the template in file 'mytemplate.ejs'. It might look like:
<h2><%= message %></h2>
-
Renders it with {message: 'hello world'}, resulting in:
<h2>hello world</h2>
-
Inserts the result into the foo element. Foo might look like:
<div id='foo'><h2>hello world</h2></div>
You can use a template with the following jQuery modifier methods:
$('#bar').after('temp.ejs',{});
$('#bar').append('temp.ejs',{});
$('#bar').before('temp.ejs',{});
$('#bar').html('temp.ejs',{});
$('#bar').prepend('temp.ejs',{});
$('#bar').replaceWith('temp.ejs',{});
$('#bar').text('temp.ejs',{});
View can load from script tags or from files. To load from a script tag, create a script tag with a type attribute set to the template type (text/ejs
) and an id to label the template:
<script type='text/ejs' id='recipesEJS'>
<% for(var i=0; i < recipes.length; i++){ %>
<li><%=recipes[i].name %></li>
<%} %>
</script>
Render with this template like:
$("#foo").html('recipesEJS', recipeData)
Notice we passed the id of the element we want to render.
Sometimes, you simply want the rendered string. In this case, you can use $.View(TEMPLATE , data )
directly. Pass $.View the path to the template and the data you want to render:
var html = $.View("template/items.ejs", items );
The most common use case is sub templates. It's common practice to separate out an individual item's template from the items template. We'll make template/items.ejs
render an <LI>
for each item, but use the template in template/item.ejs
for the content of each item.
<% for( var i = 0; i < this.length; i++){ %>
<li>
<%= $.View("template/item.ejs", this[i]);
</li>
< % } %>
Notice, in the template this
refers to the data passed to the template. In the case of template/items.ejs
, this
is the array of items. In template/item.ejs
it will be the individual item.
It's extremely common behavior to make an Ajax request and use a template to render the result. Using the Task model from the previous $.Model section, we could render tasks like:
Task.findAll({}, function(tasks){
$('#tasks').html("views/tasks.ejs" , tasks )
})
$.View supports $.Deferred allowing very powerful, terse, and high performance syntax. If a deferred is found in the render data passed to
The Model methods findAll
, findOne
, save
or destroy
return deferreds. This allows us to rewrite the rendering of tasks into a one liner!
$('#tasks').html("views/tasks.ejs" , Task.findAll() )
This works with multiple deferreds too:
$('#app').html("views/app.ejs" , {
tasks: Task.findAll(),
users: User.findAll()
})
By default, $.View loads templates synchronously. This is because it's expected that you are either:
- Putting templates in script tags,
- Packaging templates with your JavaScript build, or
- Preloading templates
JavaScriptMVC does not recommend putting templates in script tags. Script tag templates make it hard to reuse templates across different JavaScript applications. They can also reduce load performance if your app doesn't need the templates immediately.
JavaScriptMVC recommends packaging initially used templates with your application's JavaScript and preloading templates that will be used later.
StealJS, JavaScriptMVC's build system, can process and package templates, adding them to a minified production build. Simply point steal.views(PATH, ...)
to your template.
steal.views('tasks.ejs','task.ejs');
Later, when $.View looks for that template it will use a cached copy, saving an extra Ajax request.
For templates that are not used immediately, preload and cache template them with jQuery.get
. Simply provide the url to the template and provide a dataType of 'view'. It's best to do this a short time after the inital page has loaded:
$(window).load(function(){
setTimeout(function(){
$.get('users.ejs',function(){},'view');
$.get('user.ejs',function(){},'view');
},500)
})