In javascript the only way to do some processing when getting or setting one property is using Object.defineProperty:
Object.defineProperty(person, "b", {
get : function() {
return person.firstName + ' ' + person.surname;
},
set : function(newValue) {
var names = newValue.split(' ');
person.firsname = names[0];
person.surname = names[1];
},
enumerable : true,
configurable : true
});
But this have some disadvantages:
- Isn't cross browser
- Doesn't have binding, in other words, if
firstname or surname changes, the dependent property fullname isn't changed.
- Calling
person.name when person is undefined, make an error to be throwed
- Isn't possible to trigger observers, no without additional code and aware of the depency hierachy:
firstname depends from fullname, and it can be dependency of others properties arghhh!
Due to this Ember has the concept of "property", called computed property.
It can be declared in 2 ways:
foo: Ember.computed(function({
...
}).property(dependent keys);
or when using (the default) Ember.ENV.EXTEND_PROTOTYPES = true:
foo: function() {
...
}.property(dependent keys);
The property(dependent keys), is needed because it tell to ember what is the properies that when changed, will make the property be updated.
fullname: function(key, value) {
// setter
if (value !== undefined) {
var names = value.split(' ');
this.set('firstname', names[0]);
this.set('surname', names[1]);
}
// always return the complete result, so nexts calls to this.get('fullname') will return the cached value
return this.get('firstname') + ' ' + this.get('surname');
}.property('firstname', 'surname')
Using this, you have the advantage of:
- when changing
firstname or surname to a new value, fullname is changed.
- The
beforeObserves are triggered before changing the value, and the observes are triggered after the value change.
- Any template referencing some property is updated
- More then one call to person.get('firstname'), will return a cached value, saving processing. You can disable this using
.property(..).volatile()
- Avoid null or undefined errors, when accessing null objects like:
controller.get('person.dog.name') returns undefined, if person or dog is undefined.
I hope it helps
fullName: function() { return this.get('firstName') + ' ' + this.get('lastName'); }.property('firstName', 'lastName')it still seems redundant to have both a return and a .property() - WilfredApp.SongsController = Ember.ArrayController.extend({ longSongCount: function() { var longSongs = this.filter(function(song) { return song.get('duration') > 30; }); return longSongs.get('length'); }.property('@each.duration') });You're already returning the length of longSongs so why do you need .property('@each.duration')? - Wilfred