I have a User model(Backbone.js) and I want to update its settings attribute and then save it to the server. Settings is in JSON format, and the way I have it set up is that settings is the string version and settingsJSON is the object version. I bind functions to the change event of each so that when one changes, it updates the other.
The problem I am having, is that the save method is running before the changed handler is finished running. Is there any way i could ensure that all event handlers for that model are complete or something like that?
how I’m calling it:
currentUser.get('settingsJSON').apps = appsEnabled;
currentUser.save();
My event handlers:
Initialize: function() {
var that = this;
this.on("change:settingsJSON", function(model){
model.set({settings: JSON.stringify(model.get('settingsJSON'))});
});
this.on("change:settings", function(model){
model.set({settingsJSON: JSON.parse(model.get('settings'))});
});
}
@fencliff:
The change event is firing when I run this and works properly, I had it print the new settings string to the console.
Are you sure that they are called synchronously? I added console.log('changed') to the end of the .on(change) and put console.log('saved') directly after currentUser.save() and every time the console read:
saved
changed
For now I have just made it so that I stringily the JSON and save it to settings directly before I save and that works fine.
Backbone events are executed synchronously. That means that unless you (or some library) has overridden some part of the event handling, the change handlers will have processed as soon as you execute the next line of code.
In you code example there is another problem. When you call
The
changeevent will not fire, because the value ofsettingsJSONhas not been changed, merely the contents of the object were modified. Themodel.attributes.settingsJSONis still the same object as before.The events are fired only when you call
seton the property, and the new value is a different object. For example:Another problem, it would seem, is that your event handlers, if triggered, would cause the
changeevent being fired twice for the property which was first set:To solve that issue, call
setwith{silent:true}or modify themodel.attributeshash directly.Edited with corrections by @muistooshort.
Edited again with further corrections