Reputation: 191
I write one piece of test code:
var ModelHasObjectAttribute = Backbone.Model.extend({
defaults:{
property_value:99 ,
object_attr:{"year":"1990"}
},
setYear:function(year) { // function like this cannot trigger change
var temp_object_attr = jQuery.extend({}, this.get('object_attr') ); // This shallow copy is to change the reference of object_attr,
temp_object_attr["year"] = year; // otherwise I cannot trigger 'change' event, if the value of one attribute changed but reference not changed
this.set( 'object_attr', temp_object_attr );
},
changeYear:function( year ) {
console.log("before changing, " + this.get('object_attr')['year']);
this.get('object_attr')["year"] = year;
console.log( this.get('object_attr'));
},
initialize: function () {
var classRef = this;
this.on('change:property_value', function() {
alert("heard property_value changing");
});
this.on('change:maxvalue', function() {
alert("heard maxvalue changing");
});
this.on('change:object_attr', function() {
alert('heard object_attr changing' + classRef.get('object_attr')['year']);
});
}
});
var on_instance = new ModelHasObjectAttribute ();
on_instance.set('property_value',10);
on_instance.changeYear(2015); // this line of code does not trigger default 'change' event
on_instance.setYear(2016); // this one triggered
console.log( on_instance.get('object_attr') );
For example, if I want change
to be triggered when object_attr
is changed,
I have to change the reference of the object stored under object_attr
.
just modify the value of object of object_attr
, will not trigger change
.
How can I avoid the expensive shallow copy, and also trigger change events?
Upvotes: 1
Views: 66
Reputation: 30330
That approach doesn't work because Backbone has no way to detect that you have changed the object_attr
object. This isn't so much a Backbone issue as a general JavaScript point - you can't observe object property changes (yet).
The best way to set deep attributes with change events is to use a plugin like Backbone.DeepModel, which overrides set
to work with nested attributes:
var ModelHasObjectAttribute = Backbone.Model.extend({
// ...
setYear:function(year) {
// triggers 'change' events
this.set('object_attr.year', year);
},
// ...
}
N.B. The link is to a recent fork of DeepModel. Depending on your app setup, you may need to use the (unmaintained) original version.
Upvotes: 1