Reputation: 303
I've been using underscore.js for a week now and I really like it. However, now I want to replace a single element in collection (vm.lists) with another element. I tried doing the following:
_.each(vm.lists, function (el) {
if (el.id == list.id)
el = list;
});
and:
var l = _.findWhere(vm.lists, { id: list.id });
l = list;
But none of them changes the actual item in the collection. How would I do this properly?
Upvotes: 0
Views: 2923
Reputation: 3056
You got pretty close. The issue is that you are only replacing the local variables (el
and l
) pointing to the value, and this does not modify the initial list. A simpler example:
var list = [1, 2, 3];
var v = list[1];
v = 7; // v will now point to a new value, but list will stay intact [1, 2, 3]
Same with objects:
var olist = [{id: 1, v: 2}, {id: 4, v: 6}];
var obj = olist[0];
obj = {id: 8, v: 10}; // changes what obj points to, but does not affect olist[0]
var obj2 = olist[0];
obj2.v = 777; // olist[0] still points to the same object but the object is modified
olist[0] = {id: 8, v: 10}; // changes what olist[0] points to
So basically you have two options:
a) change vm.lists[index]
so that it points to a new object. You would need to get the index of the object in the list and do vm.lists[index] = newObject;
. Note that some underscore predicates also provide you the index _.each(list, function (el, index) {});
.
b) change the object that vm.lists[index]
points to, but you would need to copy fields manually. For example, if your object is represented as {id: id, values: [1, 2, 3], anotherField: data}
, you could copy the fields:
//el.id = list.id; // don't need this as you were searching by id
el.values = list.values;
el.anotherField = list.anotherField;
IMO the first option would be cleaner.
Upvotes: 2
Reputation: 1191
there is no need for underscore here:
for (var i = 0, l = vm.lists.length; i < l; i++)
{
var el = vm.lists[i];
if (el.id == list.id) {
vm.lists[i] = list;
break; // stop the for loop
}
}
Upvotes: 0