EJS is CanJS's default template language, which provides live
binding when used with Observes. EJS is very easy to use; you write the HTML you
want to be in the template, along with a few magic tags where you want dynamic
behavior.
Here's an example of a template that might render a list of Todos:
As you can see from the template and the call to can.view, the todos
object becomes this inside the template. EJS can also access the properties
of the this object without having to prefix it with this.:
<% %> will run any JavaScript code inside of it. This tag doesn't modify or
populate the template, but allows you to use for loops, if/else statements,
switch statements, and variable declarations inside the EJS template. Because
almost any JavaScript code is valid in <% %>, EJS is incredibly powerful.
Due to constraints necessary for live binding to function, it is heavily
encouraged to only have one line of JS code per pair of EJS tags in order to
ensure that the correct scope is maintained.
<%= %> will evaluate a JavaScript statement and write the HTML-escaped result
into the populated template. For example, an EJS template like this:
<div>My favorite element is <%= '<b>blink</b>' %>.</div>
will result in HTML like this:
<div>My favorite element is <b>blink</b>.</div>
This is almost always the tag you want to use when writing values to your
template, because it protects you against cross-site scripting attacks.
<%== %> will evaluate a JavaScript statement and write the raw result into the
populated template. This is like <%= %> but without escaping the result first.
For example, an EJS template like this:
<div>My favorite element is <%== '<b>blink</b>' %>.</div>
will result in HTML like this:
<div>My favorite element is <b>blink</b>.</div>
The most common use of <%== %> is to include templates in other templates:
The other two magic tags are less commonly used and can be found in the
documentation for EJS.
Live binding
Live binding will automatically update your EJS templates in the DOM whenever
the data they are populated with changes. To do this, populate your templates
with Observes and use attr to read properties. In this template, using
attr sets up live binding on the description property of todo:
<li><%= todo.attr('description') %></li>
If you change the Todo's description, the template's output will automatically
update:
todo.attr('description', 'Clean up the bathroom.');
Live binding works by wrapping the code inside the magic tags with a function
to call when the attributes inside the magic tags change. This means that a
template like this will not work:
<% for(var i = 0; i < todos.length; ++i) { %>
<li><%= todos[i].attr('name') %></li>
<% } %>
This will not work because when the function wrapping todos[i].attr('name') is
called, i will still be 3 (as that is what i is set to after the loop is
run). You can fix this by using a closure and the each method of Observes:
each will also watch the length of the list it is passed, so elements are
added or removed from it, it will update the output of the template.
Element callbacks
If the code inside <%= %> or <%== %> evaluates to a function, the function
will be called back with the element it's inside as its first argument. This is
useful to initialize functionality on an element within the template, like
starting an element hidden:
This is so common that EJS also supports ECMAScript 5 arrow functions
that get passed a library-wrapped NodeList containing the element. Because we
are using jQuery, the example above can be more simply written like this:
EJS is CanJS's default template language, which provides live binding when used with Observes. EJS is very easy to use; you write the HTML you want to be in the template, along with a few magic tags where you want dynamic behavior.
Here's an example of a template that might render a list of Todos:
And you can use
can.view
to render the template:As you can see from the template and the call to
can.view
, thetodos
object becomesthis
inside the template. EJS can also access the properties of thethis
object without having to prefix it withthis.
:Which can be inserted in the document with:
Magic tags
There are five kinds of magic tags used in EJS:
<% %>
will run any JavaScript code inside of it. This tag doesn't modify or populate the template, but allows you to use for loops, if/else statements, switch statements, and variable declarations inside the EJS template. Because almost any JavaScript code is valid in<% %>
, EJS is incredibly powerful.Due to constraints necessary for live binding to function, it is heavily encouraged to only have one line of JS code per pair of EJS tags in order to ensure that the correct scope is maintained.
<%= %>
will evaluate a JavaScript statement and write the HTML-escaped result into the populated template. For example, an EJS template like this:will result in HTML like this:
This is almost always the tag you want to use when writing values to your template, because it protects you against cross-site scripting attacks.
<%== %>
will evaluate a JavaScript statement and write the raw result into the populated template. This is like<%= %>
but without escaping the result first. For example, an EJS template like this:will result in HTML like this:
The most common use of
<%== %>
is to include templates in other templates:The other two magic tags are less commonly used and can be found in the documentation for EJS.
Live binding
Live binding will automatically update your EJS templates in the DOM whenever the data they are populated with changes. To do this, populate your templates with Observes and use
attr
to read properties. In this template, usingattr
sets up live binding on thedescription
property oftodo
:If you change the Todo's description, the template's output will automatically update:
Live binding works by wrapping the code inside the magic tags with a function to call when the attributes inside the magic tags change. This means that a template like this will not work:
This will not work because when the function wrapping
todos[i].attr('name')
is called,i
will still be 3 (as that is whati
is set to after the loop is run). You can fix this by using a closure and theeach
method of Observes:each
will also watch the length of the list it is passed, so elements are added or removed from it, it will update the output of the template.Element callbacks
If the code inside
<%= %>
or<%== %>
evaluates to a function, the function will be called back with the element it's inside as its first argument. This is useful to initialize functionality on an element within the template, like starting an element hidden:This is so common that EJS also supports ECMAScript 5 arrow functions that get passed a library-wrapped NodeList containing the element. Because we are using jQuery, the example above can be more simply written like this:
You can use this functionality to easily attach data to an element. A common reason to do this is to attach a Model to the element that represents it: