can
Version:
MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.
286 lines (219 loc) • 7.35 kB
Markdown
@page can.stache.Helpers Helpers
@parent can.stache.pages 4
# Helpers
Helpers are functions that can be registered and called from within templates. While stache is
intended to be logic-less, helpers enable the execution of logic from within a stache template.
Stache includes a number of built-in helpers, but custom helpers can be registered as well.
The majority of these built-in helpers have [can.stache.Basics basic tag] equivalents.
## Built-in Helpers
The `[can.stache.tags.section {{#if key}}]` helper is used for **if** statements. The **if** helper is equivalent
to using a `[can.stache.tags.section {{#key}}]` section. If they key passed to the helper is **truthy**, the
section will be rendered.
Template:
{{#if friends}}
I have friends!
{{/if}}
Data:
{
friends: true
}
Result:
I have friends!
When using the `[can.stache.helpers.if {{#if key}}]` helper, or any other helper for that matter,
the special `[can.stache.helpers.else {{else}}] helper becomes available. `{{else}}` is equivalent to
an [can.stache.helpers.inverse {{^key}}] inverse section (rendering **falsey** data), except that it
only uses a single tag and exists inside
a helper section.
Template:
<ul>
{{#if friends}}
</li>{{name}}</li>
{{else}}
<li>No friends.</li>
{{/if}}
</ul>
Data:
{
friends: false
}
Result:
<ul>
<li>No friends.</li>
</ul>
The `[can.stache.helpers.unless {{#unless key}}]` helper is equivalent to using a
`[can.stache.helpers.inverse {{^key}}]` inverse section. If they key passed to the helper is **falsey**, the
section will be rendered.
Template:
{{#unless friends}}
You don't have any friends!
{{/unless}}
Data:
{
friends: []
}
Result:
You don't have any friends!
The `[can.stache.helpers.each {{#each key}}]` helper is equivalent to using a
`[can.stache.tags.section {{#key}}]` section for iterating an array. In this case, the entire array
will be rendered using the inner text item by item.
Template:
<ul>
{{#each friends}}
<li>{{name}}</li>
{{/each}}
</ul>
Data:
{
friends: [
{ name: "Austin" },
{ name: "Justin" }
]
}
Result:
<ul>
<li>Austin</li>
<li>Justin</li>
</ul>
The `[can.stache.helpers.with {{#with key}}]` helper is equivalent to using a
`[can.stache.tags.section {{#key}}]` section for regular objects. The helper will change
the current context so that all tags inside will look for keys on the local context first.
Template:
<h1>Hi {{name}}</h1>
{{#with friend}}
<p>You have a new friend: {{name}}</p>
{{/with}}
Data:
{
name: "Andy",
friend: { name: "Justin" }
}
Result:
<h1>Hi Austin</h1>
<p>You have a new friend: Justin</p>
When using the `[can.mustache.helpers.is {{#is key1 key2}}]` helper you can simply compare
key1 and key2. If the result of comparsion is **truthy**, the section will be rendered.
Template:
<ul>
{{#is name 'Alex'}}
</li>Your name is {{name}}</li>
{{else}}
<li>Your name is not Alex!</li>
{{/is}}
</ul>
Data:
{
name: 'John'
}
Result:
<ul>
<li>Your name is not Alex!</li>
</ul>
The `[can.stache.helpers.data {{data key}}]` helper is another special helper for data associations that
will save the current context on the active DOM element with [can.data].
Template:
<ul>
<li id="personli" {{data 'person'}}>{{name}}</li>
</ul>
Data:
{
name: 'Austin'
}
The data can be retrieved later with:
var nameObject = can.data(can.$('#personli'), 'person');
## Registering Helpers
You can register your own global helper with the `[can.stache.registerHelper registerHelper]` method, or
a local helper (just accessible by the template being rendered) by passing in an object containing helper functions to [can.view].
Localization is a good example of a custom helper you might implement
in your application. The below example takes a given key and
returns the localized value using
[jQuery Globalize](https://github.com/jquery/globalize).
can.stache.registerHelper('l10n', function(str, options){
return Globalize != undefined
? Globalize.localize(str)
: str;
});
Or another way to do this:
can.view("//path/to/template.stache", data, {
l10n: function(str, options){
return Globalize != undefined
? Globalize.localize(str)
: str;
}
})
In the template, invoke the helper by calling the helper
name followed by any additional arguments.
Template:
<span>{{l10n 'mystring'}}</span>
Result:
<span>my string localized</span>
__Helpers with can.Map attributes__
If a can.Map attribute is passed as an argument to a helper, it is converted to a can.compute getter/setter function. This is to allow creating 2-way binding type functionality between a can.Map attribute and a form element. For example in your template:
<div>{{addPrefix name}}</div>
Your helper would look like:
var item = new can.Map({name: "Brian"}),
frag = can.view("#template", item, {
addPrefix: function(name){
return "Mr." + name()
}
});
Note we're calling `name()` in order to read its contents.
__Multiple Arguments__
You can pass multiple arguments just by putting a space between
that and the previous argument like so:
{{helper 'cat' 'hat'}}
can.stache.registerHelper('helper', function(arg1, arg2, options){
// arg1 -> 'cat'
// arg2 -> 'hat'
});
__Evaluating Helpers__
If you want to use a helper with a [can.stache.Sections section], you need to call
`options.fn(context)` in your return statement. This will return a
string with the resulting evaluated [can.stache.Sections section].
Similarly, you can call `options.inverse(context)` to evaluate the
template between an `{{else}}` tag and the closing tag.
For example, when a route matches the string passed to our
routing helper it will show/hide the text.
can.stache.registerHelper('routing', function(str, options){
if (can.route.attr('filter') === str)
return options.fn(this);
}
});
{{#routing 'advanced'}}
You have applied the advanced filter.
{{/routing}}
__Advanced Helpers__
Helpers can be passed normal objects, native objects like numbers and strings,
as well as a hash object. The hash object will be an object literal containing
all ending arguments using the `key=value` syntax. The hash object will be provided
to the helper as `options.hash`. Additionally, when using [can.stache.Sections section] with the helper,
you can set a custom context by passing the object instead of `this`.
can.stache.registerHelper('exercise', function(group, action,
num, options){
if (group && group.length > 0 && action && num > 0) {
return options.fn({
group: group,
action: action,
where: options.hash.where,
when: options.hash.when,
num: num
});
}
else {
return options.inverse(this);
}
});
{{#exercise pets 'walked' 3 where='around the block' when=time}}
Along with the {{#group}}{{.}}, {{/group}}
we {{action}} {{where}} {{num}} times {{when}}.
{{else}}
We were lazy today.
{{/exercise}}
{
pets: ['cat', 'dog', 'parrot'],
time: 'this morning'
}
This would output:
Along with the cat, dog, parrot, we walked around the block
3 times this morning.
Whereas an empty data object would output:
We were lazy today.