joshuapoehls
joshuapoehls

Reputation: 35237

Why does my Backbone model hasChanged() always return false?

Given the following snippet:

var m = new Backbone.Model({
    name: 'joshua'
});

m.set('name', 'something else');

If I now call m.hasChanged() or m.hasChanged('name') I get false. Why? My understanding is that both of these should return true.

m.changedAttributes() also returns false.

Here is a fiddle that illustrates what I'm doing, and expecting: http://jsfiddle.net/9cvVv/88/

EDIT: It seems that unless you pass { silent: true; } to the set() method then it will fire the change event on your model which clears out the changedAttributes(), etc. Essentially these properties only track changes since the last time the change event was triggered.

I read that in the documentation but didn't really understand it at first.

This doesn't seem very useful to me. I would appreciate any explanation of why this works the way it does and the best way to achieve the result I want. (Passing around {silent: true; } and giving up usage of the change event seems like a waste.)

Upvotes: 14

Views: 7068

Answers (3)

pimlottc
pimlottc

Reputation: 3126

This post is premised on the previous behavior of older versions of Backbone. hasChanged does now (as of 0.9.10) always returns true after set(..) is called. The silent flag no longer has any effect.

This is confusingly masked in the jsfiddle linked in the question which uses a CDN-hosted copy of backbone.js which always uses the latest version. Here's some updated jsfiddles showing the change in behavior:

Upvotes: 11

meirish
meirish

Reputation: 98

Model.set() takes an attributes hash as the first argument. Try m.set({'name': 'something else'});. Doing m.set('name', 'something') doesn't set 'name', so it never triggers the change event and your call to hasChanged() returns false. You can always inspect the current value of the attributes hash by logging out m.attributes - though accessing and manipulating it directly isn't recommended as none of the change events will fire that way.

Upvotes: -7

joshuapoehls
joshuapoehls

Reputation: 35237

Unless you pass { silent: true; } to the set() method then it will fire the change event on your model which clears out the changedAttributes(), etc. Essentially these properties only track changes since the last time the change event was triggered.

So the answer is to call this instead:

m.set('name', 'something else', {silent: true})

Upvotes: 15

Related Questions