can.stache

  • function
can/view/stache 2.1
 

Live binding Mustache and Handlebars-comptable templates.

can.stache(template)

Processes the template and returns a renderer function that renders the template with data and local helpers.

Parameters

  1. template {String}

    The text of a mustache template.

Returns

{renderer(data, helpers)}

A renderer function that returns a live document fragment that can be inserted in the page.

Use

Stache templates are a mustache and handlebars compatable syntax. They are used to:

  • Convert data into HTML.
  • Update the HTML when observable data changes.
  • Provide custom elements and bindings.

The following creates a stache template, renders it with data, and inserts the result into the page:

// renderer is a "renderer function"
var renderer = can.stache("<h1>Hello {{subject}}</h1>");

// "renderer functions" render a template and return a
// document fragment.
var fragment = renderer({subject: "World"})

// A document fragment is a collection of elements that can be 
// used with jQuery or with normal DOM methods.
fragment //-> <h1>Hello World</h1>
document.body.appendChild(fragment)

Render a template with observable data like can.Maps or can.Lists and the HTML will update when the observable data changes.

var renderer = can.stache("<h1>Hello {{subject}}</h1>");
var map = new can.Map({subject: "World"});
var fragment = renderer(map)
document.body.appendChild(fragment)

map.attr("subject","Earth");

document.body.innerHTML //-> <h1>Hello Earth</h1>

There's a whole lot of behavior that can.stache provides. The following walks through the most important stuff:

Differences from can.mustache

can.stache is largely compatable with can.mustache. There are three main differences:

Passing values in the scope to can.Components

A can.mustache template passes values from the scope to a can.Component by specifying the key of the value in the attribute directly. For example:

can.Component.extend({
  tag: "my-tag",
  template: "<h1>{{greeting}}</h1>"
});
var template = can.mustache("<my-tag greeting='message'></my-tag>");

var frag = template({
  message: "Hi"
});

frag //-> <my-tag greeting='message'><h1>Hi</h1></my-tag>

With stache, you wrap the key with {}. For example:

can.Component.extend({
  tag: "my-tag",
  template: "<h1>{{greeting}}</h1>"
});
var template = can.stache("<my-tag greeting='{message}'></my-tag>");

var frag = template({
  message: "Hi"
});

frag //-> <my-tag greeting='{message}'><h1>Hi</h1></my-tag>

If the key was not wrapped, the template would render:

frag //-> <my-tag greeting='message'><h1>message</h1></my-tag>

Because the attribute value would be passed as the value of greeting.

Section renderers return documentFragments

A Mustache section renderer called like options.fn() or options.inverse() would always return a String. For example, the following would wrap the .fn section in an <h1> tag:

can.mustache.registerHelper("wrapH1", function(options.fn()){
   return "<h1>"+options.fn()+"</h1>";
});

var template = can.mustache("{{#wrapH1}}Hi There!{{/#wrapH1}}");
template() //-> <h1>Hi There</h1>

can.stache's section renderers return documentFragments when sections are not contained within an html element. This means the result of the previous helper would be:

<h1>[object DocumentFragment]</h1>

Instead, helper functions should manipulate the document fragment into the desired response. With jQuery, this can be done like:

can.stache.registerHelper("wrapH1", function(options.fn()){
   return $("<h1>").append( options.fn() );
});

var template = can.stache("{{#wrapH1}}Hi There!{{/#wrapH1}}");
template() //-> <h1>Hi There</h1>

Element callbacks are no longer supported

can.mustache supported element callbacks like {{(el) -> CODE}}. These are not supported in can.stache. Instead, create a helper that returns a function or register a custom attribute.

can.stache.registerHelper("elementCallback", function(){
  return function(el){
    CODE
  }
});

can.view.tag("element-callback", function(el){
  CODE
})

Working with Promises

Promises passed into a template have the following attributes that are observable:

  • isPending
  • isResolved
  • isRejected
  • value - the resolved value of the promise, only available if isResolved is true
  • reason - the rejected value, only available if isRejected is true
  • state - "pending", "resolved", or "rejected"

Stache Template

<script id="template" type="text/stache">
    {{#if items.isPending}}
        <img src="loading.png"/>
    {{/if}}

    {{#if items.isResolved}}
        {{#each items.value}}
            <h2>{{name}}</h2>
        {{/each}}
    {{/if}}

    {{#if items.isRejected}}
        <img src="error.png"/>
    {{/if}}
</script>

JavaScript

var promise = $.get('/items');
var template = can.view('template', { items: promise });

Tags

{{key}}

Insert the value of the key into the output of the template.

{{{key}}}

Behaves just like {{key}} and {{helper}} but does not escape the result.

{{&key}}

The `{{&key}}` tag is an alias for {{{key}}}, behaving just like {{key}} and {{helper}} but does not escape the result.

{{#key}}BLOCK{{/key}}

Render blocks of text one or more times, depending on the value of the key in the current context.

{{/key}}

Ends a {{#key}} or [can.stache.tags.sectionHelper {{#helper}}] block.

{{^key}}BLOCK{{/key}}

Render blocks of text if the value of the key is falsey.

{{>key}}

Render another template within the current template.

{{!key}}

The comment tag operates similarly to a `` tag in HTML.