Ember.Handlebars.helpers Class


Module: ember-htmlbars

Show:

Methods

Show:

action

public

The {{action}} helper provides a useful shortcut for registering an HTML element within a template for a single DOM event and forwarding that interaction to the template's controller or specified target option.

If the controller does not implement the specified action, the event is sent to the current route, and it bubbles up the route hierarchy from there.

For more advanced event handling see Ember.Component

Use

Given the following application Handlebars template on the page

1
2
3
<div {{action 'anActionName'}}>
  click me
</div>

And application code

1
2
3
4
5
6
App.ApplicationController = Ember.Controller.extend({
  actions: {
    anActionName: function() {
    }
  }
});

Will result in the following rendered HTML

1
2
3
4
5
<div class="ember-view">
  <div data-ember-action="1">
    click me
  </div>
</div>

Clicking "click me" will trigger the anActionName action of the App.ApplicationController. In this case, no additional parameters will be passed.

If you provide additional parameters to the helper:

1
<button {{action 'edit' post}}>Edit</button>

Those parameters will be passed along as arguments to the JavaScript function implementing the action.

Event Propagation

Events triggered through the action helper will automatically have .preventDefault() called on them. You do not need to do so in your event handlers. If you need to allow event propagation (to handle file inputs for example) you can supply the preventDefault=false option to the {{action}} helper:

1
2
3
4
<div {{action "sayHello" preventDefault=false}}>
  <input type="file" />
  <input type="checkbox" />
</div>

To disable bubbling, pass bubbles=false to the helper:

1
<button {{action 'edit' post bubbles=false}}>Edit</button>

If you need the default handler to trigger you should either register your own event handler, or use event methods on your view class. See Ember.View 'Responding to Browser Events' for more information.

Specifying DOM event type

By default the {{action}} helper registers for DOM click events. You can supply an on option to the helper to specify a different DOM event name:

1
2
3
<div {{action "anActionName" on="doubleClick"}}>
  click me
</div>

See Ember.View 'Responding to Browser Events' for a list of acceptable DOM event names.

Specifying whitelisted modifier keys

By default the {{action}} helper will ignore click event with pressed modifier keys. You can supply an allowedKeys option to specify which keys should not be ignored.

1
2
3
<div {{action "anActionName" allowedKeys="alt"}}>
  click me
</div>

This way the {{action}} will fire when clicking with the alt key pressed down.

Alternatively, supply "any" to the allowedKeys option to accept any combination of modifier keys.

1
2
3
<div {{action "anActionName" allowedKeys="any"}}>
  click me with any key pressed
</div>

Specifying a Target

There are several possible target objects for {{action}} helpers:

In a typical Ember application, where templates are managed through use of the {{outlet}} helper, actions will bubble to the current controller, then to the current route, and then up the route hierarchy.

Alternatively, a target option can be provided to the helper to change which object will receive the method call. This option must be a path to an object, accessible in the current context:

1
2
3
4
{{! the application template }}
<div {{action "anActionName" target=view}}>
  click me
</div>
1
2
3
4
5
6
App.ApplicationView = Ember.View.extend({
  actions: {
    anActionName: function() {}
  }
});

Additional Parameters

You may specify additional parameters to the {{action}} helper. These parameters are passed along as the arguments to the JavaScript function implementing the action.

1
2
3
4
5
{{#each people as |person|}}
  <div {{action "edit" person}}>
    click me
  </div>
{{/each}}

Clicking "click me" will trigger the edit method on the current controller with the value of person as a parameter.

bind-attr

(options) String deprecated public

bind-attr allows you to create a binding between DOM element attributes and Ember objects. For example:

1
<img {{bind-attr src=imageUrl alt=imageTitle}}>

The above handlebars template will fill the <img>'s src attribute with the value of the property referenced with imageUrl and its alt attribute with the value of the property referenced with imageTitle.

If the rendering context of this template is the following object:

1
2
3
4
{
  imageUrl: 'http://lolcats.info/haz-a-funny',
  imageTitle: 'A humorous image of a cat'
}

The resulting HTML output will be:

1
<img src="http://lolcats.info/haz-a-funny" alt="A humorous image of a cat">

bind-attr cannot redeclare existing DOM element attributes. The use of src in the following bind-attr example will be ignored and the hard coded value of src="/failwhale.gif" will take precedence:

1
<img src="/failwhale.gif" {{bind-attr src=imageUrl alt=imageTitle}}>

bind-attr and the class attribute

bind-attr supports a special syntax for handling a number of cases unique to the class DOM element attribute. The class attribute combines multiple discrete values into a single attribute as a space-delimited list of strings. Each string can be:

  • a string return value of an object's property.
  • a boolean return value of an object's property
  • a hard-coded value

A string return value works identically to other uses of bind-attr. The return value of the property will become the value of the attribute. For example, the following view and template:

1
2
3
4
5
  AView = View.extend({
    someProperty: function() {
      return "aValue";
    }.property()
  })
1
<img {{bind-attr class=view.someProperty}}>

Result in the following rendered output:

1
<img class="aValue">

A boolean return value will insert a specified class name if the property returns true and remove the class name if the property returns false.

A class name is provided via the syntax somePropertyName:class-name-if-true.

1
2
3
AView = View.extend({
  someBool: true
})
1
<img {{bind-attr class="view.someBool:class-name-if-true"}}>

Result in the following rendered output:

1
<img class="class-name-if-true">

An additional section of the binding can be provided if you want to replace the existing class instead of removing it when the boolean value changes:

1
<img {{bind-attr class="view.someBool:class-name-if-true:class-name-if-false"}}>

A hard-coded value can be used by prepending : to the desired class name: :class-name-to-always-apply.

1
<img {{bind-attr class=":class-name-to-always-apply"}}>

Results in the following rendered output:

1
<img class="class-name-to-always-apply">

All three strategies - string return value, boolean return value, and hard-coded value – can be combined in a single declaration:

1
<img {{bind-attr class=":class-name-to-always-apply view.someBool:class-name-if-true view.someProperty"}}>

Parameters:

options Object

Returns:

String
HTML string

bindAttr

(context, options) String deprecated public

See bind-attr

Parameters:

context Function
options Object

Returns:

String
HTML string

debugger

public

Execute the debugger statement in the current template's context.

1
{{debugger}}

When using the debugger helper you will have access to a get function. This function retrieves values available in the context of the template. For example, if you're wondering why a value {{foo}} isn't rendering as expected within a template, you could place a {{debugger}} statement and, when the debugger; breakpoint is hit, you can attempt to retrieve this value:

1
> get('foo')

get is also aware of keywords. So in this situation

1
2
3
{{#each items as |item|}}
  {{debugger}}
{{/each}}

You'll be able to get values from the current item:

1
> get('item.name')

You can also access the context of the view to make sure it is the object that you expect:

1
> context

each

public

The {{#each}} helper loops over elements in a collection. It is an extension of the base Handlebars {{#each}} helper.

The default behavior of {{#each}} is to yield its inner block once for every item in an array.

1
var developers = [{name: 'Yehuda'},{name: 'Tom'}, {name: 'Paul'}];
1
2
3
4
{{#each developers key="name" as |person|}}
  {{person.name}}
  {{! `this` is whatever it was outside the #each }}
{{/each}}

The same rules apply to arrays of primitives.

1
var developerNames = ['Yehuda', 'Tom', 'Paul']
1
2
3
{{#each developerNames key="@index" as |name|}}
  {{name}}
{{/each}}

Specifying Keys

The key option is used to tell Ember how to determine if the array being iterated over with {{#each}} has changed between renders. By helping Ember detect that some elements in the array are the same, DOM elements can be re-used, significantly improving rendering speed.

For example, here's the {{#each}} helper with its key set to id:

1
2
{{#each model key="id" as |item|}}
{{/each}}

When this {{#each}} re-renders, Ember will match up the previously rendered items (and reorder the generated DOM elements) based on each item's id property.

There are a few special values for key:

  • @index - The index of the item in the array.
  • @item - The item in the array itself. This can only be used for arrays of strings or numbers.
  • @guid - Generate a unique identifier for each object (uses Ember.guidFor).

{{else}} condition

{{#each}} can have a matching {{else}}. The contents of this block will render if the collection is empty.

1
2
3
4
5
{{#each developers as |person|}}
  {{person.name}}
{{else}}
  <p>Sorry, nobody is available for this task.</p>
{{/each}}

if

public

Use the if block helper to conditionally render a block depending on a property. If the property is "falsey", for example: false, undefined null,"",0` or an empty array, the block will not be rendered.

1
2
3
4
{{! will not render if foo is falsey}}
{{#if foo}}
  Welcome to the {{foo.bar}}
{{/if}}

You can also specify a template to show if the property is falsey by using the else helper.

1
2
3
4
5
6
{{!Is it raining outside?}}
{{#if isRaining}}
  Yes, grab an umbrella!
{{else}}
  No, it's lovely outside!
{{/if}}

You are also able to combine else and if helpers to create more complex conditional logic.

1
2
3
4
5
6
7
{{#if isMorning}}
  Good morning
{{else if isAfternoon}}
  Good afternoon
{{else}}
  Good night
{{/if}}

You can use if inline to conditionally render a single property or string. This helper acts like a ternary operator. If the first property is truthy, the second argument will be displayed, if not, the third argument will be displayed

1
{{if useLongGreeting "Hello" "Hi"}} Dave

Finally, you can use the if helper inside another helper as a subexpression.

1
{{some-component height=(if isBig "100" "10")}}

link-to

(routeName, context, options) String public

The {{link-to}} helper renders a link to the supplied routeName passing an optionally supplied model to the route as its model context of the route. The block for {{link-to}} becomes the innerHTML of the rendered element:

1
2
3
{{#link-to 'photoGallery'}}
  Great Hamster Photos
{{/link-to}}

You can also use an inline form of {{link-to}} helper by passing the link text as the first argument to the helper:

1
{{link-to 'Great Hamster Photos' 'photoGallery'}}

Both will result in:

1
2
3
<a href="/hamster-photos">
  Great Hamster Photos
</a>

Supplying a tagName

By default {{link-to}} renders an <a> element. This can be overridden for a single use of {{link-to}} by supplying a tagName option:

1
2
3
{{#link-to 'photoGallery' tagName="li"}}
  Great Hamster Photos
{{/link-to}}
1
2
3
<li>
  Great Hamster Photos
</li>

To override this option for your entire application, see "Overriding Application-wide Defaults".

By default {{link-to}} is enabled. any passed value to disabled helper property will disable the link-to helper.

static use: the disabled option:

1
2
3
{{#link-to 'photoGallery' disabled=true}}
  Great Hamster Photos
{{/link-to}}

dynamic use: the disabledWhen option:

1
2
3
{{#link-to 'photoGallery' disabledWhen=controller.someProperty}}
  Great Hamster Photos
{{/link-to}}

any passed value to disabled will disable it except undefined. to ensure that only true disable the link-to helper you can override the global behaviour of Ember.LinkComponent.

1
2
3
4
5
6
7
8
Ember.LinkComponent.reopen({
  disabled: Ember.computed(function(key, value) {
    if (value !== undefined) {
      this.set('_isDisabled', value === true);
    }
    return value === true ? get(this, 'disabledClass') : false;
  })
});

see "Overriding Application-wide Defaults" for more.

Handling href

{{link-to}} will use your application's Router to fill the element's href property with a url that matches the path to the supplied routeName for your router's configured Location scheme, which defaults to Ember.HashLocation.

Handling current route

{{link-to}} will apply a CSS class name of 'active' when the application's current route matches the supplied routeName. For example, if the application's current route is 'photoGallery.recent' the following use of {{link-to}}:

1
2
3
{{#link-to 'photoGallery.recent'}}
  Great Hamster Photos
{{/link-to}}

will result in

1
2
3
<a href="/hamster-photos/this-week" class="active">
  Great Hamster Photos
</a>

The CSS class name used for active classes can be customized for a single use of {{link-to}} by passing an activeClass option:

1
2
3
{{#link-to 'photoGallery.recent' activeClass="current-url"}}
  Great Hamster Photos
{{/link-to}}
1
2
3
<a href="/hamster-photos/this-week" class="current-url">
  Great Hamster Photos
</a>

To override this option for your entire application, see "Overriding Application-wide Defaults".

Supplying a model

An optional model argument can be used for routes whose paths contain dynamic segments. This argument will become the model context of the linked route:

1
2
3
App.Router.map(function() {
  this.resource("photoGallery", {path: "hamster-photos/:photo_id"});
});
1
2
3
{{#link-to 'photoGallery' aPhoto}}
  {{aPhoto.title}}
{{/link-to}}
1
2
3
<a href="/hamster-photos/42">
  Tomster
</a>

Supplying multiple models

For deep-linking to route paths that contain multiple dynamic segments, multiple model arguments can be used. As the router transitions through the route path, each supplied model argument will become the context for the route with the dynamic segments:

1
2
3
4
5
App.Router.map(function() {
  this.resource("photoGallery", {path: "hamster-photos/:photo_id"}, function() {
    this.route("comment", {path: "comments/:comment_id"});
  });
});

This argument will become the model context of the linked route:

1
2
3
{{#link-to 'photoGallery.comment' aPhoto comment}}
  {{comment.body}}
{{/link-to}}
1
2
3
<a href="/hamster-photos/42/comments/718">
  A+++ would snuggle again.
</a>

Supplying an explicit dynamic segment value

If you don't have a model object available to pass to {{link-to}}, an optional string or integer argument can be passed for routes whose paths contain dynamic segments. This argument will become the value of the dynamic segment:

1
2
3
App.Router.map(function() {
  this.resource("photoGallery", {path: "hamster-photos/:photo_id"});
});
1
2
3
{{#link-to 'photoGallery' aPhotoId}}
  {{aPhoto.title}}
{{/link-to}}
1
2
3
<a href="/hamster-photos/42">
  Tomster
</a>

When transitioning into the linked route, the model hook will be triggered with parameters including this passed identifier.

Allowing Default Action

By default the {{link-to}} helper prevents the default browser action by calling preventDefault() as this sort of action bubbling is normally handled internally and we do not want to take the browser to a new URL (for example).

If you need to override this behavior specify preventDefault=false in your template:

1
2
3
{{#link-to 'photoGallery' aPhotoId preventDefault=false}}
  {{aPhotoId.title}}
{{/link-to}}

Overriding attributes

You can override any given property of the Ember.LinkComponent that is generated by the {{link-to}} helper by passing key/value pairs, like so:

1
2
3
{{#link-to  aPhoto tagName='li' title='Following this link will change your life' classNames='pic sweet'}}
  Uh-mazing!
{{/link-to}}

See Ember.LinkComponent for a complete list of overrideable properties. Be sure to also check out inherited properties of LinkComponent.

Overriding Application-wide Defaults

{{link-to}} creates an instance of Ember.LinkComponent for rendering. To override options for your entire application, reopen Ember.LinkComponent and supply the desired values:

1
2
3
4
Ember.LinkComponent.reopen({
  activeClass: "is-active",
  tagName: 'li'
})

It is also possible to override the default event in this manner:

1
2
3
Ember.LinkComponent.reopen({
  eventName: 'customEventName'
});

Parameters:

routeName String
context [Object]
options [Object]
Handlebars key/value pairs of options, you can override any property of Ember.LinkComponent

Returns:

String
HTML string

linkTo

(routeName, context) String deprecated private

See link-to

Parameters:

routeName String
context [Object]

Returns:

String
HTML string

loc

(str) public

Calls Ember.String.loc with the provided string. This is a convenient way to localize text within a template: javascript Ember.STRINGS = { '_welcome_': 'Bonjour' }; handlebars <div class='message'> {{loc '_welcome_'}} </div> html <div class='message'> Bonjour </div> See Ember.String.loc for how to set up localized string references.

Parameters:

str String
The string to format

log

(values) public

log allows you to output the value of variables in the current rendering context. log also accepts primitive types such as strings or numbers. handlebars {{log "myVariable:" myVariable }}

Parameters:

values *

query-params

(hash) String public

This is a sub-expression to be used in conjunction with the link-to helper. It will supply url query parameters to the target route.

Example

{{#link-to 'posts' (query-params direction="asc")}}Sort{{/link-to}}

Parameters:

hash Object
takes a hash of query parameters

Returns:

String
HTML string

unless

public

The unless helper is the inverse of the if helper. Its block will be rendered if the expression contains a falsey value. All forms of the if helper can also be used with unless.

with

(options) String public

Use the {{with}} helper when you want to alias a property to a new name. This is helpful for semantic clarity as it allows you to retain default scope or to reference a property from another {{with}} block.

If the aliased property is "falsey", for example: false, undefined null, "", 0 or an empty array, the block will not be rendered.

1
2
3
4
5
6
7
8
9
{{! Will only render if user.posts contains items}}
{{#with user.posts as |blogPosts|}}
  <div class="notice">
    There are {{blogPosts.length}} blog posts written by {{user.name}}.
  </div>
  {{#each blogPosts as |post|}}
    <li>{{post.title}}</li>
  {{/each}}
{{/with}}

Without the as operator, it would be impossible to reference user.name in the example above.

NOTE: The alias should not reuse a name from the bound property path. For example: {{#with foo.bar as |foo|}} is not supported because it attempts to alias using the first part of the property path, foo. Instead, use {{#with foo.bar as |baz|}}.

Parameters:

options Object

Returns:

String
HTML string