Reputation:
Let's say I have Article
s which are backed by Source
s. Each article has one source.
Sources have associated HTML which will be rendered on screen.
I want this HTML to be rendered only if the source changed.
App.ArticleView = Ember.View.extend({
didInsertElement: function() {
this.addObserver('controller.source.id', function() {
console.log(arguments);
renderHTML();
});
});
});
This behaves exactly as stated in the addObserver documentation, "Note that the observers are triggered any time the value is set, regardless of whether it has actually changed. Your observer should be prepared to handle that."
If setting a controller.model
of Article
A
with source 1
is followed by setting a controller.model
of Article
B
with source 1
, the observer will call the method but I want to prevent renderHTML() from happening.
The documentation mentions "Observer Methods" which I'm not sure how to put to use in this case. Its signature (function(sender, key, value, rev) { };
) looks exactly like what I need, but in my tests the arguments
to the observer method are always 0: (current view), 1: "controller.source.id"
.
How can I get the previous value of controller.source.id
, so as to determine whether to renderHTML()
or not?
Upvotes: 2
Views: 2205
Reputation: 47367
Ember.set
won't set the value if it's the same as the current value, so your observer won't fire unless the value changes.
Here's an example:
http://emberjs.jsbin.com/jiyesuzi/2/edit
And here's the code in Ember.set
that does it (https://github.com/emberjs/ember.js/blob/master/packages_es6/ember-metal/lib/property_set.js#L73)
// only trigger a change if the value has changed
if (value !== currentValue) {
Ember.propertyWillChange(obj, keyName);
if (MANDATORY_SETTER) {
if ((currentValue === undefined && !(keyName in obj)) || !obj.propertyIsEnumerable(keyName)) {
Ember.defineProperty(obj, keyName, null, value); // setup mandatory setter
} else {
meta.values[keyName] = value;
}
} else {
obj[keyName] = value;
}
Ember.propertyDidChange(obj, keyName);
}
Unfortunately for you're case, Ember considers changing a portion of the chain as changing the item, aka if controller.source
changes, then the observer will fire. You'll need to track your id differently to avoid you're observer from firing. You can create a different observer that always sets the current id
on a local property, and then it won't fire the update when the chain is broken.
currentArticleId: null,
watchArticle: function(){
this.set('currentArticleId', this.get('article.id'));
}.observes('article.id')
And then you would watch controller.currentArticleId
Upvotes: 1