backbone
backbone copied to clipboard
changedAttributes() behaving weird
I am using Model.changedAttributes() to write a computed field helper, but there's an issue where changedAttributes returns false when not expected (at least not by me).
Reproduced in this pen.
console.clear();
let Backbone = window.Backbone;
var m = new Backbone.Model();
let log = (txt, obj) => document.write(txt + ' ', JSON.stringify(obj)+ '<br/>');
let lastChange;
m.on('change', () => {
log('Before', lastChange);
lastChange = m.changedAttributes(lastChange);
log('After', lastChange);
});
m.set('search', 'some text');
// Why does this emit "false"? It was changed!
m.set('search', '');
m.set('search', 'some other text');
I need the lastChange because there are multiple instances of that code on a model instance. I use it to determine dependency changes (for computed fields).
Is this expected behavior?
Looking into it, when passing the diff object during a change or change:* event, we compare against the previous attributes and not the current. Meaning, you're comparing {search: 'some text'} against {search: 'some text'}.
I think what you want is closer to model.changedAttributes(), or _.pick(model.changedAttributes(), 'search');.
I'm not sure that the previous attributes behavior is what's expected here. Someone else want to weigh in?
Stumbled upon this very problem today and imho it is a bug.
According to documentation the change event is triggered "when a model's attributes have changed". "have changed" - not "are about to change". So a call to changedAttributes in a change handler should imho compare to the current attributes, not the previous ones.
Alas the internal _changing property is reset to false only after the change event is triggered. Thus changedAttributes, when being called with the diff parameter, compares to the previous attributes.