Scope and Context
Every part of a stache template is rendered with a
given scope. The scope is used to lookup
values. A scope can contain multiple places to lookup values. Each of those
places is called a context.
This is very similar to how last is looked up in the following JavaScript:
var message = "Hello"
function outer(){
var last = "Abril";
function inner(){
var first = "Alexis";
console.log(message + " "+ first + " " + last);
}
inner();
}
outer();
JavaScript looks for last in the inner context and then walks up the
scope to the outer context to find a last variable.
Let’s look at what happens with the scope the following example:
<!-- Template -->
<h1>{{message}} {{#person}}{{first}} {{last}}{{/person}}</h1>
/* Data */
{
person: { first: "Alexis" },
last: "Abril",
message: "Hello"
}
<!-- Result -->
<h1>Hello Alexis Abril</h1>
- The template is rendered with
Dataas the only item in the scope.scope:[Data] {{message}}is looked up withinData.{{#person}}adds thepersoncontext to the top of the scope.scope:[Data,Data.person]{{first}}is looked up in the scope. It will be found onData.person.{{last}}is looked up in the scope.lastis looked inData.person, it’s not found.lastis looked up inDataand returned.
{{/person}}removespersonfrom the scope.scope:[Data]
The context used to lookup a value can be controlled with adding ../ or ./ before a
key. For instance, if we wanted to make sure last was only going to lookup on person,
we could change the template to:
<!-- Template -->
<h1>{{message}} {{#person}}{{first}} {{./last}}{{/person}}</h1>
/* Data */
{
person: { first: "Alexis" },
last: "Abril",
message: "Hello"
}
<!-- Result -->
<h1>Hello Alexis</h1>
Sections, Helpers, and custom elements can modify the scope used to render a subsection.
key modifiers like ../ and @key can control the context and value that
gets returned.
Preventing Scope Walking
In order to prevent walking up the scope, you can explicitly choose the context a value is read from.
As mentioned above, you can explicitly read from the current context using ./ before the key:
<!-- Template -->
<h1>{{message}} {{#person}}{{first}} {{./last}}{{/person}}</h1>
/* Data */
{
person: { first: "Alexis" },
last: "Abril",
message: "Hello"
}
<!-- Result -->
<h1>Hello Alexis</h1>
You can also explicitly read from the parent context using ../:
<!-- Template -->
<h1>{{#person}}{{../message}} {{first}}{{/person}}</h1>
/* Data */
{
person: { first: "Alexis", message: "Hello" },
message: "Hi"
}
<!-- Result -->
<h1>Hi Alexis</h1>
You can also create unique scope variables using Hash Expressions.
In the {{#each}} helper:
{{#each(todos, todo=value num=index)}}
<li data-index="{{num}}">{{todo.name}}</li>
{{/each}}
…and the {{#with}} helper:
{{#with(street=person.address.street city=person.address.city)}}
Street: {{street}}
City: {{city}}
{{/with}}
You can also always read from the root scope using scope.root. This allows you to read data from the context you passed to your renderer function even in loops or recursive templates:
<span>{{scope.root.message}}{{name}}</span>
{{#./child}}
<div>
{{>*self}}
</div>
{{/child}}