Legacy Scope Behavior
Every part of a stache template is rendered with a
given scope. The scope is used to lookup
values. A scope looks in a single context by default with
methods to look up values from above.
In this example, {{last}} has no output because the context of the {{#person}} block doesn't contain a last property:
<!-- Template -->
<h1>{{message}} {{#person}}{{first}} {{last}}{{/person}}</h1>
{
person: { first: "Alexis" },
last: "Abril",
message: "Hello"
}
<!-- Result -->
<h1>Hello Alexis</h1>
A scope can walk up the contexts to find the property with the scope.find(...) method.
This is very similar to how last is looked up in the following JavaScript:
const message = "Hello";
function outer() {
const last = "Abril";
function inner() {
const 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}} {{scope.find('last')}}{{/person}}</h1>
{
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.- from
{{scope.find('last')}},lastis 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 specified with adding ../ before a
key. For instance, if we wanted to make sure last was going to look up above person,
we could change the template to:
<!-- Template -->
<h1>{{message}} {{#person}}{{first}} {{../last}}{{/person}}</h1>
{
person: { first: "Alexis", last: "*****" },
last: "Abril",
message: "Hello"
}
<!-- Result -->
<h1>Hello Alexis Abril</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.
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}}