Expressions

edit this page

Expressions allow you to use logic within a template. At their simplest, that may just mean a basic arithmetic operation, such as converting to percentages, or making your index references start at 1 rather than 0:

<div class='bar-chart'>
  {{#bars:i}}
    <div style='width: {{ value * 100 }}%;'>{{ i + 1 }}</div>
  {{/bars}}
</div>

Or it could mean formatting a currency so that 1.79 renders as £1.79p:

<p>Price: <strong>{{ format( price ) }}</strong></p>

Or it could mean adding a class based on some condition:

<a class='button {{ active ? "on" : "off" }}'>switch</a>

Or it could mean filtering a list to exclude certain records:

<ul>
{{# exclude( list, 'N/A' ) }}
  <li>{{author}}: {{title}}</li>
{{/ end of filter }}
</ul>

These are all examples casually plucked from the air - whether they would be useful or not in real life depends on what you're trying to do. The point is that you can include more of your view logic at the declarative layer - the template - where it's easier to reason about.

Valid expressions

These are, of course, JavaScript expressions. Almost any valid JavaScript expression can be used, with a few exceptions:

Aside from a subset of global objects (e.g. Math, Array, parseInt, encodeURIComponent - full list below), any references must be to properties (however deeply nested) of the Ractive instance's data, rather than arbitrary variables. Reference resolution follows the normal process.

Does this use eval?

Yes and no. You've probably read that 'eval is evil', or some other such nonsense. The truth is that while it does get abused, and can theoretically introduce security risks when user input gets involved, there are some situations where it's both necessary and sensible.

But repeatedly evaling the same code is a performance disaster. Instead, we use the Function constructor, which is a form of eval, except that the code gets compiled once instead of every time it executes.

A note about efficiency

Using the Function constructor instead of eval is just one way that Ractive optimises expressions. Consider a case like this:

{{a}} + {{b}} = {{ a + b }}
{{c}} + {{d}} = {{ c+d }}

At parse time, Ractive generates an abstract syntax tree (AST) from these expressions, to verify that it's a valid expression and to extract any references that are used. It then 'stringifies' the AST, so that the expression can later be compiled into a function.

As anyone who has seen minified JavaScript can attest, JavaScript cares not one fig what your variables are called. It also doesn't care about whitespace. So both of the expressions can be stringified the same way:

"_0+_1"

(To minimise the risk of accidentally breaking things by including a string or property name in the expression that contains an underscore followed by an integer, we write the sequence as ${0}+${1} during transportation from parser to renderer.)

When we evaluate {{ a + b }} or {{ c+d }}, we can therefore use the same function but with different arguments. Recognising this, the function only gets compiled once, after which it is cached. (The cache is shared between all Ractive instances on the page.) Further, the result of the evaluation is itself cached (until one or more of the dependencies change), so you can repeat expressions as often as you like without creating unnecessary work.

All of this means that you could have an expression within a list section that was repeated 10,000 times, and the corresponding function would be created once at most, and only called when necessary.

The this reference

Within an expression, you can use this to refer to the current context:

<ul>
  {{#items}}
    <!-- here, `this` means 'the current array member' -->
    <li>{{this.toUpperCase()}}</li>
  {{/items}}
</ul>

In regular mustache, we have something called the implicit iterator - {{.}} - which does the same thing. Ractive allows you to use this in place of . for purely aesthetic reasons.

Supported global objects