Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Model's change event won't fire when updating an array?

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
like image 480
fancy Avatar asked Dec 13 '11 15:12

fancy


3 Answers

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:

addIndex = (index) =>
    array = @model.get('array')
    array.push index
    @model.trigger('change:array',@model, array)
like image 100
Edward M Smith Avatar answered Nov 06 '22 21:11

Edward M Smith


Since you're setting the referenced object, use _.clone().

test = _.clone @model.get('test')
test.push num
@model.set test: test

Since you're no longer using the referenced object/array to set itself, it will fire the change event if it has changed.

like image 28
joshvermaire Avatar answered Nov 06 '22 22:11

joshvermaire


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...

like image 28
Brian Genisio Avatar answered Nov 06 '22 21:11

Brian Genisio