Reputation: 4721
Assume I have one backbone model with state
var myModel = new Backbone.Model(
{
key1:'value1',
key2:'value2',
key3:'value3'
});
myModel.on('all', function allHanlder () {
console.log(arguments);
})
I need remove key1 and key2 and change key3. Possible options are
option 1 results in 3 change, 3 change attribute events
myModel.unset('key1');
myModel.unset('key2');
myModel.set({key3:'newValue3'})
//events
["change:key1", Object { cid="c1355", attributes={...}, _changing=true, more...}, undefined, Object { unset=true}]
["change", Object { cid="c1355", attributes={...}, _changing=true, more...}, Object { unset=true}]
["change:key2", Object { cid="c1355", attributes={...}, _changing=true, more...}, undefined, Object { unset=true}]
["change", Object { cid="c1355", attributes={...}, _changing=true, more...}, Object { unset=true}]
["change:key3", Object { cid="c1355", attributes={...}, _changing=true, more...}, "newValue3", Object {}]
["change", Object { cid="c1355", attributes={...}, _changing=true, more...}, Object {}]
option 2 will result in 2 change change:attribute events
myModel.clear()
myModel.set({key3:'newValue3'})
//output
["change:key1", Object { cid="c1356", attributes={...}, _changing=true, more...}, undefined, Object { unset=true}]
["change:key2", Object { cid="c1356", attributes={...}, _changing=true, more...}, undefined, Object { unset=true}]
["change:key3", Object { cid="c1356", attributes={...}, _changing=true, more...}, undefined, Object { unset=true}]
["change", Object { cid="c1356", attributes={...}, _changing=true, more...}, Object { unset=true}]
["change:key3", Object { cid="c1356", attributes={...}, _changing=true, more...}, "newValue3", Object {}]
["change", Object { cid="c1356", attributes={...}, _changing=true, more...}, Object {}]
change:attribute events are fair, but I need to minimise change triggers. Something like below.
myModel.someMagicSet({key3:'newValue3'})
//output
["change:key1", Object { cid="c1355", attributes={...}, _changing=true, more...}, undefined, Object {}]
["change:key2", Object { cid="c1355", attributes={...}, _changing=true, more...}, undefined, Object {}]
["change:key3", Object { cid="c1355", attributes={...}, _changing=true, more...}, "newValue3", Object {}]
["change", Object { cid="c1355", attributes={...}, _changing=true, more...}, Object {}]
Is there is a way I can achieve it without overriding backbone behaviours?
Upvotes: 1
Views: 447
Reputation: 7810
myModel.unset('key1', {silent: true});
myModel.unset('key2', {silent: true});
myModel.set({key3:'newValue3'}, {removed: ['key1', 'key2']});
This will do what you want while only triggering one change event. You are passing in the removed items to your handler in the options object. In your handler, your code should look like this:
myModel.on('all', function allHandler (model, options) {
console.log(options.removed); // this should show you what has been removed before
// other code
})
Alternately, you could pass a flag in your options with each event which you could analyze in your handler, which would determine whether the handler was run or not. This would give your handler access to what has been changed, but it would have to store it outside of it's own scope in order to access it the next time.
myModel.unset('key1', {finished: false});
myModel.unset('key2', {finished: false});
myModel.set({key3:'newValue3'}, {finished: true});
EDIT: Here is a one liner that should do everything:
myModel.clear({reset: {key3: 'newValue3'}});
and then in your handler do this
myModel.on('all', function allHandler (model, options) {
if (options.reset){
model.set(options.reset);
}
// other code
})
The thing you should watch out for is that clear
removes the id too, so if you need that you should pass it in with your options:
myModel.clear({reset: {key3: 'newValue3', id: myModel.get('id')}});
Upvotes: 1