Using backbone.js...
@model.bind 'change', ()-> console.log 'updated'
addIndex = (index) =>
array = @model.get('array')
array.push index
@model.set
array: array
This updates the model perfectly but doesn't trigger the change event. Does anyone know why from looking at what I posted?
EDIT:
I added this and it triggers the change event:
@model.set
test: ''
num = 0
setInterval ()=>
num++
@model.set
test: num
, 3000
I added this and it doesn't trigger the change event:
@model.set
test: []
num = 0
setInterval ()=>
console.log 'testupdate'
num++
test = @model.get('test')
test.push num
@model.set
test: test
, 3000
Could you consider using a Backbone collection instead of an array, and then binding to change events in that collection?
The problem is that you are setting the value with the existing value. Take a look at the source code:
http://documentcloud.github.com/backbone/docs/backbone.html#section-33
When you call
set
it has a guard clause to make sure that you are not setting the same value (to avoid event loops). In your case, you are getting the array, modifying it, and setting it again, which will not trigger your event.Of course, when you
set test: {}
, it is a new item with a new object, so it will trigger again. If you really want to trigger the event, you can set it to null, then set it to an empty array and then to the populated array again...Another way to go, when changing objects or arrays, is to silently unset the property before setting the new updated value. Something like this:
By setting
silent: true
when unsetting the prop, the change event will only fire once (When theset()
method is called and the property has been updated).There isn't really a difference between doing this or manually calling the event, it's just a matter of personal preference.
Brian's answer as to the reason is awesome!
Wanted to present another way to get what you want instead of nulling it out or cloning the array.
Just manually trigger the change yourself:
Since you're setting the referenced object, use
_.clone()
.Since you're no longer using the referenced object/array to set itself, it will fire the change event if it has changed.