3

I'm trying to do what I hope is a simple thing -- doing a model.set only on a sub attribute of the object.

Right now, I have a model that looks like this:

{
            "attr1" : true,
            "attr2" : this.model.get("username"),
            "attr3" : $('#tenant_select').val(),
            "attr_array": [
                {
                    "id": "sub_1",
                    "state": "active"
                },
                {
                    "id": "sub_22",
                    "state": "not_active"
                }
            ]
        }

I want to be able to grab reach into myMode.attr_array.state and change the value. However, using .set I've only been able to change attributes on the first level, i.e. attr_array.

Is there an way to do this using model.set?

streetlight
  • 5,968
  • 13
  • 62
  • 101
  • I bet if you just `.get()` the value of "attr_array" and modify the array contents, that'd work. – Pointy Apr 18 '13 at 13:46
  • That works, but the issue is that I want to maintain the order of everything inside and right now my solution re-orders consistently – streetlight Apr 18 '13 at 13:58

1 Answers1

18

You can do it (I'm wondering why you didn't manage to do it). But you have to be careful:

var array = this.get('attr_array');
array[1].state = 'active';
this.set('attr_array', array);

What's the problem here? Your model holds a reference of the object. Therefore the last line is useless, it won't change anything at all. It's simply equivalent to:

this.get('attr_array')[1].state = 'active';

And you lose any internal stuff Backbone does when you use set.
So what to do? Clone your object:

var array = _.clone(this.get('attr_array'));
array[1].state = 'active';
this.set('attr_array', array); // will trigger 'change' and 'change:attr_array' events
Loamhoof
  • 8,293
  • 27
  • 30
  • Ahh, the cloning did the trick. I had a fix working like the first one you mentioned, but the last one is perfect! Thanks again! – streetlight Apr 18 '13 at 14:05