DoneJS StealJS jQuery++ FuncUnit DocumentJS
3.14.1
5.0.0 4.3.0 2.3.35
  • About
  • Guides
  • API Docs
  • Community
  • Contributing
  • Bitovi
    • Bitovi.com
    • Blog
    • Design
    • Development
    • Training
    • Open Source
    • About
    • Contact Us
  • About
  • Guides
  • API Docs
    • Observables
      • can-compute
      • can-define
      • can-define/list/list
      • can-define/map/map
      • can-define-stream
      • can-define-stream-kefir
      • can-event
      • can-event/async/async
      • can-event/batch/batch
      • can-event/lifecycle/lifecycle
      • can-kefir
      • can-list
      • can-map
      • can-map-backup
      • can-map-define
      • can-observation
      • can-observe
      • can-simple-map
      • can-simple-observable
      • can-stream
      • can-stream-kefir
    • Data Modeling
      • can-connect
      • can-connect-cloneable
      • can-connect-feathers
      • can-connect-ndjson
      • can-connect-signalr
      • can-fixture
      • can-fixture-socket
      • can-ndjson-stream
      • can-set
    • Views
      • can-component
      • can-ejs
      • can-element
      • can-react-component
      • can-stache
        • Pages
          • Magic Tag Types
          • Scope and Context
          • Expressions
          • Template Acquisition
          • Helpers
          • Live Binding
          • Whitespace Control
          • Sections
        • Methods
          • addHelper
          • addLiveHelper
          • from
          • registerConverter
          • registerHelper
          • registerPartial
          • registerSimpleHelper
          • safeString
        • Tags
          • {{expression}}
          • {{{expression}}}
          • {{#expression}}
          • {{/expression}}
          • {{^expression}}
          • {{>key}}
          • {{!expression}}
          • {{<partialName}}
          • {{else}}
        • Expressions
          • Bracket Expression
          • Call Expression
          • Hash Expression
          • Helper Expression
          • KeyLookup Expression
          • Literal Expression
        • Key Operators
          • @at
          • ~compute
          • ./current
          • ../parent
          • scope
          • %special
          • this
          • *variable
          • *self
          • key
        • Helpers
          • {{#if(expression)}}
          • {{#unless(expression)}}
          • {{#each(expression)}}
          • {{#with(expression)}}
          • {{log()}}
          • {{debugger()}}
          • {{#eq(expressions)}}
          • {{#is(expressions)}}
          • {{#switch(expression)}}
          • {{#case(expression)}}
          • {{#default()}}
          • {{joinBase(expressions)}}
        • Types
          • getterSetter
          • helper
          • helperOptions
          • renderer
          • sectionRenderer
          • simpleHelper
      • can-stache/helpers/route
      • can-stache-bindings
      • can-stache-converters
      • can-view-autorender
      • can-view-callbacks
      • can-view-href
      • can-view-import
      • can-view-live
      • can-view-model
      • can-view-nodelist
      • can-view-parser
      • can-view-scope
      • can-view-target
      • react-view-model
      • react-view-model/component
      • steal-stache
    • Routing
      • can-deparam
      • can-param
      • can-route
      • can-route-pushstate
    • JS Utilities
      • can-assign
      • can-define-lazy-value
      • can-globals
      • can-key-tree
      • can-make-map
      • can-parse-uri
      • can-string
      • can-string-to-any
      • can-util
      • can-zone
      • can-zone-storage
    • DOM Utilities
      • can-ajax
      • can-attribute-encoder
      • can-control
      • can-dom-events
      • can-event-dom-enter
      • can-event-dom-radiochange
      • can-jquery
    • Data Validation
      • can-define-validate-validatejs
      • can-validate
      • can-validate-interface
      • can-validate-legacy
      • can-validate-validatejs
    • Typed Data
      • can-cid
      • can-construct
      • can-construct-super
      • can-namespace
      • can-reflect
      • can-reflect-promise
      • can-types
    • Polyfills
      • can-symbol
      • can-vdom
    • Core
    • Infrastructure
      • can-global
      • can-test-helpers
    • Ecosystem
    • Legacy
  • Community
  • Contributing
  • GitHub
  • Twitter
  • Chat
  • Forum
  • News
Bitovi

Scope and Context

  • Edit on GitHub

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>
  1. The template is rendered with Data as the only item in the scope. scope:[Data]
  2. {{message}} is looked up within Data.
  3. {{#person}} adds the person context to the top of the scope. scope:[Data,Data.person]
  4. {{first}} is looked up in the scope. It will be found on Data.person.
  5. {{last}} is looked up in the scope.
    1. last is looked in Data.person, it’s not found.
    2. last is looked up in Data and returned.
  6. {{/person}} removes person from 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}}

CanJS is part of DoneJS. Created and maintained by the core DoneJS team and Bitovi. Currently 3.14.1.

On this page

Get help

  • Chat with us
  • File an issue
  • Ask questions
  • Read latest news