1. THE ROAD TO EMBER 2.0
FIRST EMBER.JS TREVISO MEETUP
presented by /Filippo Zanella @r4m
2. HURRY UP!
On July 24th Ember.js will bump to version 2.0.
The core team is moving fast (one release per monthly sprint)
Apr 4th v1.11.1, May 13th v1.12, June 12th v1.13.
3. ...BUT DON'T BE SCARED.
Version 2.0 marks the transformation of Ember from simply an MVC
framework to a complete front-end stack.
Luckily, Ember 2.0 is not a big-bang rewrite. Staying on the
cutting-edge can be done without rewriting your app.
Changes have been rolled out incrementally. The 2.0 release will
simply remove features that have been deprecated.
5. STABILITY WITHOUT STAGNATION
In the greater JavaScript community, getting the latest and
greatest often means rewriting parts of your apps once a year.
The Ember community works hard to introduce new ideas with an
eye towards migration. The Ember core-team call this "stability
without stagnation".
When breaking changes are absolutely necessary, they try to make
those changes ones you can apply without too much thought. They
call these "mechanical" refactors.
To further aid in these transitions, a new tab to the Ember
Inspector that will list all deprecations in your application.
6. BIG BETS
The first bet was on open standards: JavaScript modules, promises
and Web Components.
The second bet was that the community was tired of hand-rolling
their own build scripts for each project. They've invested heavily in
Ember CLI, giving us a single tool that unifies the community and
provides a venue for disseminating great ideas.
In Ember 2.0, Ember CLI and ES6 modules will become first-class
parts of the Ember experience.
That is, you should begin moving your app to Ember CLI now.
7. LEARNING FROM COMMUNITY
Ember core-team have analyzed and discussing React's approach
to data flow and rendering and in particular how they make use of a
"virtual DOM" to improve performance.
Ember's view layer is one of the oldest parts of Ember, and was designed for a world where IE7 and IE8 were
dominant (gosh!). They've spent the better part of 2014 rethinking the view layer to be more DOM-aware, and the
new codebase (codenamed "HTMLBars") borrows the best ideas from React.
React's "virtual DOM" abstraction also allowed them to simplify the
programming model of component-based applications.
In Ember 2.0, a "virtual DOM" and data flow model has been
adopted to simplifies communication between components.
8. SIMPLIFYING EMBER CONCEPTS
Ember 2.0 is about simplification, to reduce file sizes, reduce code
complexity, and generally make apps easier to maintain.
The high-level set of improvements that we have planned are:
More intuitive attribute bindings
New HTML syntax for components
Block parameters for components
More consistent template scope
1-way data binding by default, with opt-in to 2-way bindings
More explicit communication between components
Routes drive components, instead of controller + template
Improved actions that are invoked inside components
10. INLINE IF
In v1.11 Ember's ifhelper can be used in the inline form:
{{if isEnabled 'active' 'disabled'}}
11. EACH WITH INDEX
The eachhelper will support an indexblock param in v1.11:
{{#each people as |person index|}}
{{!-- The first index value will be 0 --}}
<div>{{index}}: {{person.name}}</div>
{{/each}}
12. BOUND ATTRIBUTE SYNTAX
Current Ember developers are familiar with the bind-attr
syntax, used to declare an attribute binding on an HTML element.
<a {{bind-attr href=url}}>Click here</a>
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}}>
13. COMPONENT HELPER
Ember components can be bound via the componenthelper. For
example this logic in a template:
{{#if isRed}}
{{x-red}}
{{else if isBlue}}
{{x-blue}}
{{else if isGreen}}
{{x-green}}
{{/if}}
Can be replaced by a property and the componenthelper.
{{component colorComponentName}}
The property colorComponentNameshould either have a value
of x-red, or x-blueetc. As the value of the computed property
changes, the rendered component will also change.
14. STORE.UNLOADALL()
Previously, store.unloadAllrequired a modelNameargument
to unload records of a type. Now, you can unload all records
without calling store.destroy.
@store.unloadAll()can now unload all models when not
passed a model name.
15. GLIMMER
Ember 1.13 is the first release that includes the new Glimmer
rendering engine. Glimmer is:
A new faster rendering engine that is especially fast at updates.
An implementation of the React-inspired "just re-render it"
programming model for components, with one-way data flow by
default and better enforcement for data-down, actions-up.
Supports ergonomic attributes (<my-link href="
{{url}}.html">go home</my-link>), angle-bracket
components (<my-component />), that hews closely to HTML
syntax with a few small enhancements.
16. THE ATTRSPROPERTY
Beginning with Ember 1.13 a component's attributes will be
available in this.attrsrather than on the component itself.
So when a component is invoked this way:
{{my-component title=model.name}}
The component will see this.attrs.titleas the current value
of model.name. Whenever model.namechanges via
observation, or when the parent component is re-rendered, my-
component's lifecycle hooks will be triggered, and it will see a new
version of model.name.
17. THE MUTHELPER
What if you want to allow the child component to modify the
property explicitly? The muthelper will produce an object that
contains both a valueproperty and an updatemethod.
In Ember 1.13, you can write:
{{my-counter count=(mut activatedCount)}}
Component.extend
click: ->
this.attrs.count.update(this.attrs.count.value + 1)
The call to {{mut activatedCount}}packages up an object
containing both its current value and a callback that allows the
receiving component to modify it.
18. CLOSURE ACTION
In Ember 1.x, the actions system used bubbling to pass user
behavior to a parent scope. E.g., when clicking a button an action
might bubble through several controllers.
Action bubbling was difficult to debug, and plagued by an inability
to have a return value.
Ember 2.x is component-driven, and replaces action bubbling
with a function-passing solution.
Actions:
Can be passed multiple arguments
Return a value. E.g. result = this.attrs.submit()
Can curry
19. CLOSURE ACTION
For example, action submitis passed to my-componentwhere it
is called upon click:
app/controllers/index.coffee
`import Ember from 'ember'`
Ember.Controller.extend
actions:
setName: (name) ->
model.set('name', name)
{{! app/templates/index.hbs }}
{{my-component submit=(action 'setName')}}
app/components/my-component.coffee
`import Ember from 'ember'`
Ember.Component.extend
click: ->
this.attrs.submit(this.get('name'))
20. NEW EMBER.JS HELPER API
Ember helpers:
Represent a single value
Do not manage DOM or control flow
Can recompute themselves
Can optionally access services
Do not require a dash
app/helpers/full-name.js
` `
Ember.Helper.helper (params, hash) ->
return params.join(' ')
import Ember from 'ember'
{{full-name "Daniel" model.lastName}}
{{my-component name=(full-name model.firstName "Smith")}}
{{! The following usage would set the model.name to the new full name
when my-component calls the submit action. }}
{{my-component submit=(action (mut model.name) (full-name model.firstName "Smith"
22. MORE CONSISTENT HANDLEBARS SCOPE
In Ember 1.9, the context-shifting forms of #eachand #withhave
been deprecated in favor of the named-parameter forms.
{{#each post in posts}}
{{!-- the context in here is the same as the outside context,
and `post` references the current iteration --}}
{{/each}}
{{#each posts}}
{{!-- the context in here has shifted to the individual post.
the outer context is no longer accessible --}}
{{/each}}
{{#with post as otherPost}}
{{!-- the context in here is the same as the outside context --}}
{{/with}}
{{#with post}}
{{!-- the context in here has shifted to the post.
the outer context is no longer accessible --}}
{{/with}}
23. MORE CONSISTENT HANDLEBARS SCOPE
In Ember 1.12, the inand assyntax are further deprecated in favor
of block params syntax.
To transition your code to the new syntax, you can change
templates that look like this:
{{#each people}}
<p>{{firstName}} {{lastName}}</p>
<p>{{address}}</p>
{{/each}}
with:
{{#each people itemController="abc" as |person|}}
<p>{{person.firstName}} {{person.lastName}}</p>
<p>{{person.address}}</p>
{{/each}}
24. OBJECTCONTROLLER
Experienced Ember users have enjoyed the use of proxying
behavior in the Ember.ObjectControllerclass since 1.0.
However, this behavior will be removed in Ember 2.0 as the
framework migrates to routable components.
25. OBJECTCONTROLLER
To migrate from an explicitly defined object controller, first convert
the class definition to inherit from Ember.Controller. E.g.:
import Ember from "ember";
// Change:
export default Ember.ObjectController.extend({
// To:
export default Ember.Controller.extend({
// ...
Next update any use of {{modelPropertyName}}in templates
with {{model.modelPropertyName}}. You should also review
any computed property dependent keys, observer keys, and get
and setstatements on the route and controller.
26. INSTANCES INITIALIZERS
Before FastBoot, you would only ever run applications one at a
time. In FastBoot, it is important for a single node server to be able
to serve a second request while the first one is fetching its data.
In Ember.js 1.12 application boot is separated into two phases:
Application initializers run, to register dependencies and
injections. These initializers are doing work that is shared across
all FastBoot requests, and therefore should not create instances.
Instance initializers run next. This is the right time to do work
that is specific to each FastBoot request. You can create
instances and modify their state here.
27. ACCESS TO INSTANCES IN INITIALIZERS
Previously, initializers had access to an object that allowed them to
both register new classes and get instances of those classes.
If you have an initializer that gets instances of a class, you need to
change it to use an instance initializer.
The store service is now injected as an . As a consequence, if you had initializers depending on
the store, you should move them to an instance initializer as well, and mark it as after: 'ember-data'.
instanceInitializer
28. ACCESS TO INSTANCES IN INITIALIZERS
Change code that looks like this:
App.initializer
name: "clock"
initialize: (container, application) ->
application.register("clock:main", Clock)
clock = container.lookup("clock:main")
clock.setStartTime(Date.now())
To:
App.initializer
name: "clock"
initialize: (registry, application) ->
application.register("clock:main", Clock)
App.instanceInitializer
name: "clock"
initialize: (instance) ->
clock = instance.container.lookup("clock:main")
clock.setStartTime(Date.now())
29. SHARED GETTER AND SETTER
Ember.js 1.12 introduces an improved syntax for computed
properties with a setter. Previously, computed properties with a
setter implemented that setter by inspecting the number of
arguments passed to the computed property's descriptor.
For example, this computed property splits a full name into two
parts when set:
fullName: Ember.computed "firstName", "lastName", (key, newName) ->
if (arguments.length > 1)
parts = newName.split(" ")
this.setProperties({ firstName: parts[0], lastName: parts[1] })
return newName
else
return this.get("firstName") + " " + this.get("lastName")
30. SHARED GETTER AND SETTER
These uses should be converted to use the new discrete getter and
setter syntax introduced in 1.12:
fullName: Ember.computed("firstName", "lastName", {
get: function() {
return this.get("firstName") + " " + this.get("lastName");
},
set: function(key, newName) {
var parts = newName.split(" ");
this.setProperties({ firstName: parts[0], lastName: parts[1] });
return newName;
}
});
31. EMBER.VIEW
Ember 1.x encouraged a Model-View-Controller-Route architecture.
Since then, the web has consolidated around a Model-Component-
Route pattern for web development that Ember 2.0 also embraces.
Views are removed from the Ember 2.0 API.
YES, VIEWS ARE REMOVED.
However a single release is likely insufficient for large apps to
upgrade their entire codebase away from routeable views, and
consequently Ember is providing extended support for views via
the addon.
This addon will remain compatible with Ember until v2.4 of the framework is released.
ember-legacy-views
32. EMBER.VIEW
In most cases Ember views can be replaced with a component. E.g.:
app/templates/show-menu.hbs
{{view.title}}
app/views/show-menu.coffee
` `
# Usage: {{view "show-menu"}}
Ember.View.extend
templateName: 'some-menu'
title: 'My Menu'
import Ember from 'ember'
Can be replaced with this component:
app/templates/components/show-menu.hbs
{{title}}
app/components/show-menu.coffee
` `
# Usage: {{show-menu}}
Ember.Component.extend
title: 'My Menu'
import Ember from 'ember'
33. EMBER.VIEW
Note that a component has always its own context in a template.
A view's template may have had access to other variables that were
present where it was called, such as a controller.
A component template will always be isolated, and if data is
needed it should be passed upon invocation. For example:
{{show-menu options=controller.menuOptions}}
34. EMBER.VIEW
ROUTABLE VIEWS
Currently, when a template for a given route is rendered, if there is
a view with the same name that view will also be used.
For example this view is attached to the rendered route template:
app/router.coffee
` `
Ember.Router.map ->
this.route('about')
import Ember from 'ember'
app/views/about.coffee
` `
Ember.View.extend
classNameBindings: ['controller.isActive:active']
import Ember from 'ember'
35. EMBER.VIEW
ROUTABLE VIEWS
There are only two reasons a view may be used for a route:
To set attribute bindings
To attach event handlers
To manage all the jquery stuffs
You should migrate away from routed views.
36. EMBER.VIEW
ROUTABLE VIEWS
For example to attach bindings to an element in the template is
sufficient:
app/router.coffee
` `
Ember.Router.map ->
this.route('about')
import Ember from 'ember'
app/templates/about.hbs
<div class="{{if isActive 'active'}}">
<!-- something something -->
</div>
37. EMBER.VIEW
ROUTABLE VIEWS
If attaching events or sharing DOM is necessary, consider a
component:
app/templates/about.hbs
{{#active-layout isActive=isActive}}
<!-- something something -->
{{/active-layout}}
app/components/active-layout.js
` `
Ember.Component.extend
classNameBindings: ['isActive:active']
click: ->
# Handle click
import Ember from 'ember'
38. EMBER.VIEW
NOTABLE
In preparation for Ember 2.0, 1.13 introduces many deprecations.
Some of these include:
All view APIs in Ember (Ember.CoreView, Ember.View,
Ember.CollectionView, Ember.ContainerView)
Options to the {{#eachhelper that trigger a legacy and poorly
performing legacy layer. Like: itemView, itemViewClass,
tagName, emptyViewand emptyViewClass.
The itemControllerargument for {{#each.
The viewand viewClassparams for {{outlet}}
39. EMBER.LINKVIEW
As a consequence of the deprecation of Ember.View, many
internal views have been ported to component.
Ember.LinkView, the class that backs the {{link-to}}
helper, have been ported to Ember.LinkComponent.
Most uses of Ember.LinkViewcan be directly ported to the
Ember.LinkComponentclass.
40. EMBER.SELECT
Using the Ember.Selectglobal and its view helper form
({{view 'select'}}) is deprecated.
Ember.Selectis implemented in a legacy coding style that uses
patterns such as observers and two-way data binding that:
can cause pathological performance problems
provide an experience that is not consistent with idiomatic
Ember 2.0 development.
Sadly true. Complex Ember.Selectwith mixed dynamic content are tricky to be managed.
Legacy support will be provided via the addon.ember-legacy-views
41. EMBER.SELECT
Ember 2.0 provides several new features that make it much more
straightforward to implement </select>tag functionality via the
data-down, actions-up paradigm in one's codebase.
For example, to create a component that displays a prompt and a
list of dropdown options, the following code could be used:
app/templates/components/my-select.hbs
<select {{action 'change' on='change'}}>
{{#each content key="@index" as |item|}}
<option value="{{item}}" selected={{is-equal item selectedValue}}>
{{item}}
</option>
{{/each}}
</select>
43. EMBER.SELECT
This component could be used in a template by supplying it an
array of strings as contentand an action to call when the user
makes a selection as change:
app/templates/application.hbs
The currently selected item: {{mySelectedItem}}.
{{my-select content=myItems action=(action (mut mySelectedItem))}}
myItemsis an array of strings: ['one', 'two', ...].
This uses the `action`and `mut`helpers to pass in an action
that will update the (outer scope) `mySelectedItem`property
with the user's selection.
44. TYPEKEY TO MODELNAME
In Ember Data, when you ask for a model, Ember Data looks its
class up using Ember's API. When the model
class is looked up, Ember Data stores the type on the model class.
Dependency Injection
For example, when the following code runs in your application:
post = this.store.getById('post', 1)
and Ember Data will store the string "post" on the model class:
console.log(post.constructor.typeKey) # 'post'
Ember Data uses this typeKeyproperty internally when
creating/extracting payloads in Serializers, and when locating
models in Adapters.
45. TYPEKEY TO MODELNAME
In Ember Data 1.0.0-beta.18, the typeKeyproperty is now called
modelName. In addition, the modelNameis a dasherized string
(previously it was always normalized to be a camelCased string).
For example, if you had a model called TacoShop, it would be stored on the model's constructor's modelName
property as taco-shop, whereas previously it would be stored as tacoShop.
Accessing the typeKeyproperty should still work, but will trigger
deprecation warnings.
46. IE 8
Ember Data v1.0.0-beta.19 is the last release to support Internet
Explorer 8. Future versions of Ember Data will not support IE 8.
R.I.P.
47. RESOURCES
The road to Ember.js 2.0 RFC
The transition to Ember 2.0 in detail
Deprecations added in Ember 1.X