What’s New in Ember 2.0?
This article was peer reviewed by Stephan Max. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!
Ember is an JavaScript framework, based on the model-view-controller (MVC) pattern and used for creating single page applications. Recently, version 2.0 of the framework was released under the motto “Stability without Stagnation”. What this means is that Ember 2.0 didn’t ship with any new features, as those features intended for the 2.0 release (such as the Glimmer rendering engine) were already present in previous versions.
Ember 2.0 also removes many of the older APIs which had been deprecated in the 1.x versions. This means that if you can create an Ember 1.13 app which is free from deprecation warnings, the upgrade to 2.0 will be seamless. This is in stark contrast to the furor surrounding last year’s Angular 2.0 announcement.
The features intended for Ember 2.0 have been termed “precursor features” by the Ember team. So, for the rest of this article, I will be highlighting the major precursor features and how to use them. We will also examine some of the features intended for future releases.
If you would like to follow along, you’ll need to create an Ember project using the latest version of the framework. Show me how.
Ember is installed using npm. For a tutorial on npm, you can see here.
npm install -g ember-cli
At the time of writing this will pull in version 1.13
ember -v
=> version: 1.13.8
Next, create a new Ember app:
ember new hello-world
Navigate to that directory and edit the bower.json
file to include the latest version of the Ember and ember-data
{
"name": "hello-world",
"dependencies": {
"ember": "^2.0.0",
"ember-data": "^2.0.0",
...
}
}
Back in the terminal run:
bower install
Bower might prompt you for a version resolution for Ember. Select the 2.x version from the list provided and prefix it with an exclamation mark to persist the resolution to bower.json
.
Next start Ember CLI’s development server:
ember server
Finally navigate to http://localhost:4200/ and check the version your browser’s console.
Precursor Features for Ember 2.0
Views
Views have been deprecated in favor of components. Consisting of two parts (a JavaScript component file and a Handlebars template), components are isolated by design and are better suited to reuse throughout your application (unlike views). A compatibility addon is available which will be maintained by the Ember team until version 2.6 of Ember. This is to help transition apps making heavy use of views to the latest Ember. Compatibility of this addon with Ember will stop at version 2.4. When building new Ember applications, developers should favor components over views.
ArrayController and ObjectController
ArrayController
and ObjectController
have been deprecated in favor of the generic Controller
class. This is because they created some unnecessary confusion among developers and there was ambiguity about which controller type is generated by Ember if none is specified. With this deprecation, there will only be one type of controller.
To make this transition, change code which looks like this:
exports default Ember.ObjectController.extend({
or:
exports default Ember.ArrayController.extend({
to:
exports default Ember.Controller.extend({
A controller addon is also supported until Ember 2.6 to help transition apps.
Attribute Bindings
In past, the {{bind-attr}}
helper was used to bind properties to DOM attributes. With Ember 2.0, you no longer need this helper. Instead of doing something like:
<a {{bind-attr href=location }} >Link Text</a>
You can now do something like this instead, which is much nicer and clearer
<a href={{location}} >Link Text</a>
Class Bindings
Binding classes to properties is simpler now, with the deprecation of the {{bind-attr}}
helper. For example, instead of doing this
<div {{bind-attr class="isVisible"}} ></div>
You can now do this
<div class='{{if isVisible "is-visible" }}' ></div>
View and Controller Options on the Each Helper
The following properties itemView
, itemViewClass
, tagName
, emptyView
, emptyViewClass
and itemController
have been deprecated. These were options you could set when using the {{each}}
helper. This deprecation is as a result of moving away from views and controllers towards components.
Suffice to say that components offer all the functionalities provided by these options. For example:
{{each view.comments itemController="comment"
itemView="commentView"
emptyView="noCommentsView"
tagName="ul"}}
becomes:
<ul>
{{#each comments as |comment|}}
{{post-comment comment=comment}}
{{else}}
{{no-comments}}
{{/each}}
</ul>
Block Params
Block params have been introduced. This helps with uniformity and familiarity when using several handlebars helpers. For example when using the {{each}}
helper, this code
{{#each person in people}}
now becomes
{{#each people as |person| }}
As for the {{with}}
helper, this code
{{#with teacher as person}}
now becomes
{{#with teacher as |person| }}
Controller Needs
The needs
property for controllers is gone. This used to enable a controller to have access to another controller. You can now set the controller name as a property with its value injected. So this code
exports default Ember.Controller.extend({
needs: ['application']
})
changes to:
exports default Ember.Controller.extend({
application: Ember.inject.controller()
})
You can now access the injected controller as application
. This is shorter compared to the longer form controllers.application
we used to have.
Observer Arguments Ordering
Observer arguments will now be in reverse order. The function used to be the first argument, followed by the dependent properties. Now we will have the function as the last argument instead of being first. So in essence this code
Ember.observer(function(){
}, 'someProperty1', 'someProperty2')
becomes
Ember.observer('someProperty1', 'someProperty2', function(){
})
IE8 Support
Support for Internet Explorer 8 has been dropped in Ember 2.0. From now on, only Internet Explorer 9 and above will be supported. There was even talk of dropping support for IE9, but after considerable debate, it was decided that the benefits of dropping IE9 in Ember 2.0 were not as strong.
Canary Features to Expect in Post Ember 2.0
These are some of the feature to expected when newer versions of Ember ship. For now, they are experimental and are only found in the canary build. To use them, you need to opt-in using the FEATURES
property found in the Ember config file. A list of available features can be found here.
Angle-Bracket Components
An angle bracket syntax for components has been implemented. This makes it possible to invoke components in the same style as regular HTML elements. So you can change the following code from
{{#my-component}}{{/my-component}}
to:
<my-component></my-component>
The old syntax will still work alongside the new one for the time being so as to give developers of existing applications enough time to upgrade. In addition to the cleaner syntax angle-bracket components will introduce a default one-way data flow (which you maybe know from React) and provide an opt-in for two-way data flow.
One-Way Data Flow and the Mut Keyword
In previous versions of Ember, component properties used to be bound two ways. What this means is that the property of a component as well as its data source are both mutable. In Ember 2.0, component properties are now immutable by default. This behavior is a consequence of using the new angle-bracket syntax for components. For example in the code below using the old method to invoke a component.
{{#my-component firstName=model.name }}{{/my-component}}
The firstName
property is bound to the name
property of the model. When the value of the name
property changes, the change is reflected in the firstName
property. Likewise, we could change the firstName
property and the change is reflected back in the name
property of the model.
With the new syntax (as shown below) we can only change the value for the name
property. We cannot change the value for the firstName
property, as it is read-only.
<my-component firstName=model.name ></my-component>
There is however, a new mut
keyword to circumvent this default behavior.
<my-component firstName={{mut model.name}} ></my-component>
This keyword makes the firstName
property mutable by giving it two properties. First, a function called update
which you can use to set the value of the property like so:
this.attrs.firstName.update("newFirstNameValue");
Second, a property called value
. This holds the actual value of the property and is accessible like so
this.attrs.firstName.value;
The Attrs Property in Components
Another feature introduced by the new angle-bracket components is the attr
property for components. Any property passed during invocation will not be directly present on the component, but rather in a component property called attr
. So for example, when we invoke this component:
<my-component property1="somevalue" property2="someothervalue" >
</my-component>
In the past you could get access to the two properties like this.
this.get('property1')
this.get('property2')
but with the new syntax you have to access them like so
this.attrs.property1
this.attrs.property2
React-style Fast Re-Render
In previous versions of Ember, re-rendering a component used to be a computationally expensive operation. Ember used to tear down the whole DOM for the component and rebuild it from scratch. In the new engine called Glimmer, the rerender
function is much smarter now. It only rebuilds the part of the DOM that needs to change. This allows for faster and more efficient re-renders.
Conclusion
Ember 2.0 is definitely a step in the right direction. There is a focus on uniformity and adhering to web standards which make Ember a stronger contender as a JavaScript framework to pick for your next new project. Let us know your thoughts on these new exciting features in the comments below.
And, for those of you wishing to dig into this more, I recommend watching the EmberConf2015 opening Keynote, by Tom Dale & Yehuda Katz, about everything that has happened on the way to Ember 2.0. Enjoy!