holy moly

pangratz prattles

Changes in Ember.js v0.9.6

Since the previous release 0.9.5 and the current release 0.9.6 many changes have been made. Besides the many bug fixes, added documentation and speed improvements also some new features have been added. This blog post will cover some of them. The complete changelog is listed in ember.js/CHANGELOG.

Aliased attribute bindings and possibility for static class names

It is now possible to define aliases for attributeBindings and define static class names, as already mentioned by Gordon Hempton in the excellent Eight Ember.js Gotchas With Workarounds blog post.

Use case for attribute bindings and static classes
1
2
3
4
5
6
7
8
9
10
Ember.View.create({
  template: Ember.Handlebars.compile('<div {{bindAttr class="boolAttr stringAttr isDisabled:disabled :staticClass"}}/>'),

  boolAttr: true,
  stringAttr: 'helloWorld',
  isDisabled: true,

  myThemeAttr: 'blue',
  attributeBindings: 'myThemeAttr:data-theme'.w()
}).append();

So the view is rendered as follows:

1
2
3
<div data-theme="blue" class="ember-view" >
  <div class="bool-attr helloWorld disabled staticClass" ></div>
</div>

Where the following rules apply:

  • if the property is true and no alias has been specified, the dasherized property name is added (boolAttr in the example above)
  • if the property is true and an alias has been specified, the alias is used (isDisabled:disabled in the example above)
  • if the property is a String the value is added (stringAttr in the example above)
  • if the property is a String and an alias has been specified, the alias is used for the attribute name and the value is added (myThemeAttr in the example above)
  • a static property is always added (:staticClass in the example above)

Ember.getWithDefault

It’s now possible to get a value from an object and additionally specifiy a default value which shall be returned when the object does not have a value for the specific property. The function itself is available on the Ember namespace via Ember.getWithDefault and is also aliased to Ember.Observable mixin so it’s available on Ember.Object’s.

Use case for Ember.getWithDefault
1
2
3
4
5
6
7
var myObj = Ember.Object.create({
  name: 'Sepp'
});

Ember.getWithDefault(myObj, 'name', 'Unknown'); // Sepp
myObj.getWithDefault('name', 'Unknown'); // Sepp
myObj.getWithDefault('score', 100); // 100

Ember.Map

Since 0.9.6 there is a new class Ember.Map available. As the documentation states, the keys can be any JavaScript object.

Use case for Ember.Map
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var map = Ember.Map.create();

var tobias = Ember.Object.create({name: 'Tobias'});
var lindsay = Ember.Object.create({name: 'Lindsay'});

map.set(lindsay, 'Fünke');
map.set(tobias, 'Fünke');
map.set('Maeby', 'Fünke');

map.forEach(function(key, value) {
    console.log(key, value);
});

map.get(tobias); // 'Fünke'
map.has(lindsay); // true
map.has('Maeby'); // true

map.remove(lindsay);
map.has(lindsay); // false

Ember.Evented mixin

With the Ember.Evented mixin it’s possible to add and remove listeners for custom events.

Use case for Ember.Evented
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var obj = Ember.Object.create(Ember.Evented, {
  init: function() {
    this._super();
    this.on('eventA', this, 'eventAOccured');
  },

  eventAOccured: function(param) {
    console.log('eventA occured');
  }
});

var targetObj = Ember.Object.create({
  eventBOccured: function(first, second) {
    console.log('eventB occured');
  }
});

obj.on('eventB', targetObj, 'eventBOccured');

obj.fire('eventA', 'hello'); // eventAOccured on obj is invoked with 'hello' as param
obj.fire('eventB', 1, 2); // eventBOccured on targetObj is invoked with 1 and 2 as parameters

obj.off('eventB', targetObj, 'eventBOccured'); // unregister event listener
obj.fire('eventB'); // nothing is invoked since no listener is registered for this event

Handlebars action helper has just an event argument

In the previous version the action helper invoked an action and passed 3 arguments: view, event and context.

Action helper in Ember.js v0.9.5
1
2
3
4
App.ItemView = Ember.View.extend({
  removeItem: function(view, event, context) {
  }
})

Since 0.9.6 only one argument event is passed which has the view and context stashed as properties on it.

Action helper in Ember.js v0.9.6
1
2
3
4
5
6
App.ItemView = Ember.View.extend({
  removeItem: function(event) {
    var view = event.view;
    var context = event.context;
  }
})

New attributeBindings for Ember.TextSupport, Ember.TextField and Ember.TextArea

The text controls of Ember.js learned additional properties which can be bound. These are maxlength of Ember.TextSupport, size of Ember.TextField and rows and cols of Ember.TextArea.

New attributeBindings for Ember.js text controlsJSFiddle
1
2
3
4
5
6
7
8
9
10
Ember.TextField.create({
  maxlengthBinding: 'App.maxlength',
  sizeBinding: 'App.size'
}).append();

Ember.TextArea.create({
  rowsBinding: 'App.rows',
  colsBinding: 'App.cols',
  maxlengthBinding: 'App.maxlength'
}).append();

Support for contextmenu event

The event contextmenu has been added to Ember.EventDispatcher. All handled browser events and corresponding Ember.js equivalents are defined in Ember.EventDispatcher#setup.

lowercase Namespaces are deprecated

From now on an Ember.Namespace needs to start with an uppercase letter. Just a reminder for the convention of naming classes and instances:

  • instances should start with a lowercase letter, so it’s App.controller = Ember.Object.create();
  • classes should start with an uppercase letter, so it’s App.Model = Ember.Object.extend();

This was a small roundup of the new stuff in Ember.js v0.9.6. Happy coding!

Comments