Mustaches
edit this pageWhat is Mustache?
Mustache is one of the most popular templating languages. It's a very lightweight, readable syntax with a comprehensive specification - which means that implementations (such as Ractive) can test that they're doing things correctly.
If you've used Handlebars or Angular you'll also find mustaches familiar.
What are mustaches?
Within this documentation, and within Ractive's code, 'mustache' means two things - a snippet of a template which uses mustache delimiters, such as {{name}}
, and the object within our parallel DOM that is responsible for listening to data changes and updating the (real) DOM.
We say that the {{name}}
mustache has a reference of name
. When it gets rendered, and we create the object whose job it is to represent name
in the DOM, we attempt to resolve the reference according to the current context stack. For example if we're in the user
context, and user
has a property of name
, name
will resolve to a keypath of user.name
.
As soon as the mustache knows what its keypath is (which may not be at render time, if data has not yet been set), it registers itself as a dependant of the keypath. Then, whenever data changes, Ractive scans the dependency graph to see which mustaches need to update, and notifies them accordingly.
Mustache basics
If you already know Mustache, Ractive supports all the Mustache features - basic Mustache variables like {{name}}
, as well as sections, partials, and even delimiter changes. If you're already familiar with Mustache, skip to the Extensions section below.
You can also check out the tutorials.
Variables
The most basic mustache type is the variable. A {{name}}
tag in a template will try to find the name
key in the current context. If there is no name
key in the current context, the parent contexts will be checked recursively. If the top context is reached and the name key is still not found, nothing will be rendered.
All variables are HTML escaped by default. If you want to return unescaped HTML, use the triple mustache: {{{name}}}
.
You can also use &
to unescape a variable: {{& name}}
. This may be useful when changing delimiters (see "Set Delimiter" below).
Template:
* {{name}}
* {{age}}
* {{company}}
* {{{company}}}
With the following data:
{
"name": "Chris",
"company": "<b>GitHub</b>"
}
Will generate the following output:
* Chris
*
* <b>GitHub</b>
* <b>GitHub</b>
Sections
Sections render blocks of text one or more times, depending on the value of the key in the current context.
A section begins with a pound and ends with a slash. That is, {{#person}}
begins a "person" section while {{/person}}
ends it.
The behavior of the section is determined by the value of the key.
False Values or Empty Lists
If the person key exists and has a value of false or an empty list, the HTML between the pound and slash will not be displayed.
Template:
Shown.
{{#person}}
Never shown!
{{/person}}
Data:
{
"person": false
}
Output:
Shown.
Non-Empty Lists
If the person key exists and has a non-false value, the HTML between the pound and slash will be rendered and displayed one or more times.
When the value is a non-empty list, the text in the block will be displayed once for each item in the list. The context of the block will be set to the current item for each iteration. In this way we can loop over collections.
Template:
{{#repo}}
<b>{{name}}</b>
{{/repo}}
Data:
{
"repo": [
{ "name": "resque" },
{ "name": "hub" },
{ "name": "rip" }
]
}
Output:
<b>resque</b>
<b>hub</b>
<b>rip</b>
Non-False Values
When the value is non-false but not a list, it will be used as the context for a single rendering of the block.
Template:
{{#person?}}
Hi {{name}}!
{{/person?}}
Data:
{
"person?": { "name": "Jon" }
}
Output:
Hi Jon!
Inverted Sections
An inverted section begins with a caret (hat) and ends with a slash. That is {{^person}}
begins a "person" inverted section while {{/person}}
ends it.
While sections can be used to render text one or more times based on the value of the key, inverted sections may render text once based on the inverse value of the key. That is, they will be rendered if the key doesn't exist, is false, or is an empty list.
Template:
{{#repo}}
<b></b>
{{/repo}}
{{^repo}}
No repos :(
{{/repo}}
Ractive borrows a trick from Handlebars here and lets you perform:
{{#repo}}
<b></b>
{{else}}
No repos :(
{{/repo}}
Data:
{
"repo": []
}
Output:
No repos :(
Attributes
Sections may also be used within attribute values and around attribute values. Using a conditional section around an attribute or group of attributes will exclude those attributes from the DOM when the conditional is false
and include them when it is true
. Using a conditional section within an attribute only affects the value of the attribute, and there may be multiple sections within an attribute value.
In the following terribly contrived example, if big
is truthy, then the button will have a class big
in addition to the fixed class button
. If planetsAligned
is truthy, the button will also get an annoying onmousemove
attribute. Note that ractive directives cannot currently be placed within a section, but that may change in the future.
<button class="{{#big}}big {{/}}button" {{#planetsAligned}}onmousemove="alert('I am annoying...')"{{/}}>I sure hope the planets aren't aligned...</button>
Comments
Comments begin with a bang and are ignored. The following template:
<h1>Today{{! ignore me }}.</h1>
Will render as follows:
<h1>Today.</h1>
If you'd like the comments to show up, just use html comments and set stripComments to false
.
Comments may contain newlines.
Partials
Partials begin with a greater than sign:
{{> box}}
Recursive partials are possible. Just avoid infinite loops.
They also inherit the calling context. For example:
{{> next_more}}
In this case, next_more.mustache
file will inherit the size and start methods from the calling context.
In this way you may want to think of partials as includes, or template expansion:
For example, this template and partial:
base.mustache:
<h2>Names</h2>
{{#names}}
{{> user}}
{{/names}}
With user.mustache
containing:
<strong>{{name}}</strong>
Can be thought of as a single, expanded template:
<h2>Names</h2>
{{#names}}
<strong>{{name}}</strong>
{{/names}}
Partials are a very useful construct, and you can find out more about them on the partials page.
Custom delimiters
Custom delimiters are set with a 'Set delimiter' tag. Set delimiter tags start with an equal sign and change the tag delimiters from {{
and }}
to custom strings.
{{foo}}
{{=[[ ]]=}}
[[bar]]
Custom delimiters may not contain whitespace or the equals sign.
You can also set custom delimiters using the delimiters
and tripleDelimiters
options in your Ractive instance.
var ractive = new Ractive({
el: whatever,
template: myTemplate,
data: {
greeting: 'Hello',
greeted: 'world',
triple: '<strong>This is a triple-stache</strong>'
},
delimiters: [ '[[', ']]' ],
tripleDelimiters: [ '[[[', ']]]' ]
});
Extensions
Ractive is 99% backwards-compatible with Mustache, but adds several additional features.
Array index references
Index references are a way of determining where we are within a list section. It's best explained with an example:
{{#items:i}}
<!-- within here, {{i}} refers to the current index -->
<p>Item {{i}}: {{content}}</p>
{{/items}}
If you then set items
to [{content: 'zero'}, {content: 'one'}, {content: 'two'}]
, the result would be
<p>Item 0: zero</p>
<p>Item 1: one</p>
<p>Item 2: two</p>
This is particularly useful when you need to respond to user interaction. For example you could add a data-index='{{i}}'
attribute, then easily find which item a user clicked on.
Object iteration
Mustache can also iterate over objects, rather than array. The syntax is the same as for Array indices. Given the following ractive:
ractive = new Ractive({
el: container,
template: template,
data: {
users: {
'Joe': { email: 'joe@example.com' },
'Jane': { email: 'jane@example.com' },
'Mary': { email: 'mary@example.com' }
}
}
});
We can iterate over the users object with the following:
<ul>
{{#users:name}}
<li>{{name}}: {{email}}</li>
{{/users}}
</ul>
to create:
<ul>
<li>Joe: joe@example.com</li>
<li>Jane: jane@example.com</li>
<li>Mary: mary@example.com</li>
</ul>
In previous versions of Ractive it was required to close a section with the opening keypath. In the example above {{#users}}
is closed by {{/users}}
. This is no longer the case, you can now simply close an iterator with {{/}}
. Ractive will attempt to warn you in the event of a mismatch, {{#users}}
cannot be closed by {{/comments}}
. This will not effect Expressions as they have always been able to be closed by {{/}}
.
<!--- valid markup -->
{{#users}}
{{/users}}
{{#users:i}}
{{/users}}
{{#users}}
{{/}}
{{#users.topUsers}}
<!-- still matches the first part of the keypath, thus a valid closing tag -->
{{/users}}
<!-- invalid markup -->
{{#users}}
{{/comments}}
Special references
There are a few implicit variables that are available anywhere within a ractive template.
@index
is a reference to the index or key name of the nearest iterative section. It is available even if an index name is not supplied for the section.{{#items}}{{@index + 1}} - {{.}}{{/}}
@key
is an alias for@index
, though at some point in the future Ractive may further differentiate between array and object iteration.@keypath
is the current context used to resolve references.{{#foo}}{{#bar}}{{@keypath}} - foo.bar{{/}}{{/}} {{#items}}{{#.condition}}{{@keypath}} - for the first item will be items.0.condition{{/}}{{/}}
@keypath
is particularly useful when aliasing is used and the current context outside of the aliasing is hidden.
Restricted references
Normally, references are resolved according to a specific algorithm, which involves moving up the context stack until a property matching the reference is found. In the vast majority of cases this is exactly what you want, but occasionally (for example when dealing with recursive partials) it is useful to be able to specify more specific directives about the context of a property being referenced.
See References for all available reference restrictions.
Expressions
Expressions are a big topic, so they have a page of their own. But this section is about explaining the difference between vanilla Mustache and Ractive Mustache, so they deserve a mention here.
Expressions look like any normal mustache. For example this expression converts num
to a percentage:
<p>{{ num * 100 }}%</p>
The neat part is that this expression will recognise it has a dependency on whatever keypath num
resolves to, and will re-evaluate whenever the value of num
changes.
Mustache fans may bristle at expressions - after all, the whole point is that mustache templates are logic-less, right? But what that really means is that the logic is embedded in the syntax (what are conditionals and iterators if not forms of logic?) rather than being language dependent. Expressions just allow you to add a little more, and in so doing make complex tasks simple.
Handlebars-style sections
In addition to Mustache-style conditional and iterative sections, Ractive adds Handlebars-style if
, unless
, each
, and with
to handle branching, iteration, and context control. For if
and each
, {{else}}
may be used to provide an alternate branch for a false condition or an empty iterable.
<button on-click="flip">Flip Coin</button>
<p>Coin flip result: {{#if heads}}heads{{else}}tails{{/if}}</p>
<ul>
{{#each result}}
<li>{{.}}</li>
{{else}}
<li>No results yet...</li>
{{/each}}
</ul>
<p>Here is a {{#with some.nested.value}}{{.}}{{/with}} value.</p>
var ractive = new Ractive({
el: document.body,
template: myTemplate,
data: {
results: [],
heads: true,
some: { nested: { value: 'nested' } }
}
});
ractive.on('flip', function() {
var sadRandom = Math.floor(Math.random() * 2) === 1;
this.set('heads', sadRandom);
this.unshift('results', sadRandom ? 'heads' : 'tails');
});
In this example, clicking the button gets a "random" coin flip result, sets it in an if
conditional section, and prepends it in an each
iterative section. There is also a with
context section throw in for good measure.
Aliasing
Since a section with a non-falsy value uses the value as its context, an object expression can be used to create an arbitrary context within a section. Any currently visible context keypaths can be referenced within the new context object, which allows you to keep keypaths available that would otherwise be unreachable.
{{# { id: '10t' } }}
Error: {{id}}
{{/}}
Output:
Error: 10t
Using a section with an object expression to keep references accessible or convenient:
<ul>
{{#things:outerIndex}}
{{# { thing: ., i: outerIndex } }}
{{#colors:j}}
<li>{{i}}-{{j}} {{.}} {{thing}}</li>
{{/}}
{{/}}
{{/}}
</ul>
Note i
as outerIndex
is not required, outerIndex
is still accessible within the {{#colors}}
section.
Data:
{
colors: ['Purple', 'Orange', 'Green'],
things: ['People-Eater', 'Orange', 'Hornet']
}
Output:
<ul>
<li>0-0 Purple People-Eater</li>
<li>0-1 Orange People-Eater</li>
<li>0-2 Green People-Eater</li>
<li>1-0 Purple Orange</li>
<li>1-1 Orange Orange</li>
<li>1-2 Green Orange</li>
<li>2-0 Purple Hornet</li>
<li>2-1 Orange Hornet</li>
<li>2-2 Green Hornet</li>
</ul>
Static mustaches
Sometimes it is useful to have portions of a template render once and stay the same even if their references change. A static mustache will be updated only when its template is rendered and not when its keypath is updated. So, if a static mustache is a child of a section or partial that get re-rendered, the mustache will also be re-rendered using the current value of its keypath.
The default static mustache delimiters are [[ ]]
for escaped values and [[[ ]]]
for unescaped values.
[[ foo ]] {{ foo }}
{{^flag}}
[[ foo ]]
{{/}}
var ractive = new Ractive({
data: { foo: 'bar' },
...
});
ractive.set('foo', 'bippy');
ractive.set('flag', true);
ractive.set('flag', false);
Output:
bar bippy bippy
Static mustaches may also be used for sections that should only be updated on render.
[[# if admin ]]
Hello, admin
[[else]]
Hello, normal user
[[/if]]
var ractive = new Ractive({
data: { admin: false },
...
});
ractive.set('admin', true);
Output:
Hello, normal user
Footnote
*Ractive implements the Mustache specification as closely as possible. 100% compliance is impossible, because it's unlike other templating libraries - rather than turning a string into a string, Ractive turns a string into DOM, which has to be restringified so we can test compliance. Some things, like lambdas, get lost in translation - it's unavoidable, and unimportant.