WindSaber WindSaber - 4 months ago 20
AngularJS Question

Angular modifies properties when forEach or pure For

Here's the Plunker:
https://plnkr.co/edit/itgraL2X6gCHCs7tgSZi

I have 2 collections

$scope.params = [{
id: 1,
nombre: 'bloom'
}, {
id: 2,
nombre: 'ctotal'
}, {
id: 3,
nombre: 'coliformes'
}];

$scope.puntos = [{
id: 1,
nombre: 'votator'
}, {
id: 2,
nombre: 'vw1'
}, {
id: 3,
nombre: 'preparador'
}];


My code in the controller looked like:

angular.forEach($scope.puntos, function(punto, key) {
punto.params = $scope.params;
angular.forEach(punto.params, function(pa, key) {
pa.otherProp = "xxxxx";
});
});


As you can see, I want to assign the params collection to each item in the puntos collection. Then I assign to the item inside the collection a value in the otherProp property.....I never change the main $scope.params....but if I output both this has changed too

Then my output is:

Puntos

{"id":1,"nombre":"votator","params":[{"id":1,"nombre":"bloom","otherProp":"xxxxx"},{"id":2,"nombre":"ctotal","otherProp":"xxxxx"},{"id":3,"nombre":"coliformes","otherProp":"xxxxx"}]}
{"id":2,"nombre":"vw1","params":[{"id":1,"nombre":"bloom","otherProp":"xxxxx"},{"id":2,"nombre":"ctotal","otherProp":"xxxxx"},{"id":3,"nombre":"coliformes","otherProp":"xxxxx"}]}
{"id":3,"nombre":"preparador","params":[{"id":1,"nombre":"bloom","otherProp":"xxxxx"},{"id":2,"nombre":"ctotal","otherProp":"xxxxx"},{"id":3,"nombre":"coliformes","otherProp":"xxxxx"}]}
Params

{"id":1,"nombre":"bloom","otherProp":"xxxxx"}
{"id":2,"nombre":"ctotal","otherProp":"xxxxx"}
{"id":3,"nombre":"coliformes","otherProp":"xxxxx"}


At first I tought that the problem was caused by using angular.forEach....So i decided to use a pure for.....the problem appears instead

for (var i = 0; i < $scope.puntos.length; i++) {
var punto = $scope.puntos[i];
punto.params = [];
punto.params = $scope.params;
for (var j = 0; j < punto.params.length; j++){
var pa = punto.params[j];
pa.otherProp = 'yyyyyy';
}
}


Of course this is a simmple example...what I really want is more complex but this is stopping me...

Why is the params collection modified even If i didn't change it Manually?
Hoy to prevent it?

Thanks in advance

Answer

Doing:

 punto.params = $scope.params;

you are not copying collection but create reference to it, so punto.params is the $scope.params and changing punto.params is qual to changing $scope.params. You should copy object like this:

 punto.params=angular.copy($scope.params);

Then foreach and changing punto.params will not change $scope.params.