Ember.js 1.11.0 and 1.12 Beta Released

– By Matthew Beale

We are pleased to announce the release of both Ember.js 1.11.0 and the first beta in the 1.12 series. This comes as the eleventh cycle of our release process that began after 1.0 was released.

The 1.11 release represents the effort of at least 87 contributors across over 646 commits.

New Features in Ember.js 1.11

Bound Attribute Syntax

Current Ember developers are familiar with the bind-attr syntax, used to declare an attribute binding on an HTML element. An original motivation for HTMLBars was to improve on this syntax.

Ember 1.11 introduces a more intuitive API for attribute binding. For example, here the color variable is bound to the class of a div:

<div class="{{color}}"></div>

The inline if helper can also be used in these contexts:

<div class="{{color}} {{if isEnabled 'active' 'disabled'}}"></div>

For some attributes, like the disabled boolean, passing a literal value is desirable. An example:

<input disabled={{isDisabled}}>

To allow the data-binding of non-string values to boolean properties and custom element properties, bound attributes are implemented with a property-first setter.

When binding to an attribute, Ember first checks to see if that attribute is a property of the element's DOM node (with normalization of capitalization). If it is, the value is set with a property. For example:

<input disabled={{isDisabled}}>
// disabled is a property of input elements, so...
input.disabled = true;

If the attribute is not present as a property, then its value is set as an attribute:

<div class={{color}}>
// class is not a property of div elements, do...
div.setAttribute('class', 'red');

For SVG attributes and the style attribute, we've made an exception to this pattern and use setAttribute at all times. Despite these exceptions, the property-first rule is a good way to describe what is happening behind the scenes. In practice, the binding syntax feels natural.

Many thanks to @mixonic, @_mmun, and @wycats for their effort on the design and implementation of this feature.

Escaping Content in HTMLBars

Bound attribute syntax introduces several new uses of mustaches (the {{ syntax used in Ember templates). These new uses come with new security considerations.

Two notable new considerations are mustache use inside style contexts, and inside JavaScript contexts. For example, without escaping this binding would be vulnerable to an XSS attack (via ActiveX controls) in IE8:

<div style="width: {{userProvidedWidth}}px;"></div>

Implementing CSS and JavaScript context-sensitive escaping will require further research and development. In Ember 1.11, bound style attributes will warn when the value is not marked safe.

{{! No escaping strategy, log a warning }}
<a style="width: {{someProperty}}px"></a>

The examples that follow are intended to demonstrate how this works in practice.

{{! Works as expected }}
<a class="{{someProperty}}"></a>

{{! Works as expected, and escapes unsafe urls }}
<a href="{{someProperty}}"></a>

{{! Works as expected, and escapes unsafe urls }}
<img src="{{someProperty}}"></a>

Warnings about unsafe bindings other than style will be introduced before Ember 2.0.

{{! No escaping strategy in 1.11 }}
<a onmouseover="alert('{{someProperty}}');"></a>

{{! No escaping strategy in 1.11 }}
<style>width: {{someProperty}}px</style>

Strings that are known to be adequately escaped can be passed through the htmlSafe function to mark them safe.

import Ember from "ember";

export default Ember.Component.extend({
  layout: Ember.HTMLBars.compile("<a style='width: {{someProperty}}px'>"),
  someProperty: function(){
    return Ember.String.htmlSafe(this.get('someKnownSafeProperty'));
  }.property('someKnownSafeProperty')
});

A less savory alternative is to use the {{{ "escaped mustache" style. There are plans to improve escaped content as we approach 2.0.

Inline if

In 1.11 Ember's if helper can be used in the inline form:

{{if isEnabled 'active' 'disabled'}}

Thanks to @eaf4 and @marciojunior_me for implementing this feature.

Each with Index

The each helper will support an index block param in Ember 1.11:

{{#each people as |person index|}}
  {{! The first index value will be 0 }}
  <div>{{index}}: {{person.name}}</div>
{{/each}}

Thanks to @timmyce and @_mmun for implementing this feature.

Named Substates

Two routing substates exist for Ember routes. The loading substate will be entered if the async hooks of a route are still processing, and the error substate will be entered when an async hook promise is rejected.

Substates are sibling routes. When the new route of cars.new is loading, the cars.loading substate is entered. The application route has no parent namespace to nest its siblings. This makes using the loading and error substates impossible for an application route.

Named substates add a new lookup method for substates. The name of the route is pre-pended onto the substate. So a valid loading substate for application can be defined as application_loading.

Thanks to @machty for landing this feature.

Component Helper

Ember components can be bound via the component helper. For example this logic in a template:

{{#if isRed}}
  {{x-red}}
{{else if isBlue}}
  {{x-blue}}
{{else if isGreen}}
  {{x-green}}
{{/if}}

Can now be replaced by a computed property and the component helper.

{{component colorComponentName}}

The property colorComponentName should either have a value of x-red, or x-blue etc. As the value of the property changes, the rendered component will also change.

A big thank you to @lukemelia for shipping this new feature.

Performance Improvements

Ember.js 1.10 has favorable rendering performance compared to previous releases. We're pleased that Ember 1.11 builds upon that progress. Compared to 1.10, common list rendering scenarios have improved by about twenty percent and view instance creation is over twice as fast. These measurements were made using the ember-performance repo.

Progress continues on the Glimmer rendering engine announced at EmberConf 2015. This dramatic performance improvement is expected to land in Ember.js 1.13.

Notable Deprecations in 1.11

The following deprecations are scheduled for release with Ember.js 1.11:

  • The ObjectController will be removed in Ember 2.0. In Ember 1.11, both explicitly using an ObjectController and using the proxying behavior of a generated ObjectController will raise deprecation warnings. See the deprecation guide for more details.
  • Initializing instances (via container.lookup) in initializers is deprecated. For initialization that requires instances Ember has introduced "instance initializers". See the deprecation guide for more information, as well as this documentation PR and the implementation PR.
  • Not a deprecation, but related: The {{bind}} template helper was a private helper, and has been deprecated since Ember 1.10. It has been removed in Ember.js 1.11.

Changelogs