Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular.copy() does not copy all properties

Consider the following function in a service:

$scope.addPeriod = function(newPeriod) {        
        if(newPeriod.from !== '' && newPeriod.until !== '') {           
            var index = $scope.newPeriods.indexOf(newPeriod);       
            $scope.newPeriods.splice(index, 1); 
            $scope.setHolidayEditions(newPeriod);


            console.log("Check period");
            console.log(newPeriod); // state 1: object newPeriod is as expected, it contains holidayEdtions

            console.log("Check period copy");
            console.log(angular.copy(newPeriod)); //state 2 : object newPeriod is missing the holidayeditions!
            $scope.periods.push(angular.copy(newPeriod)); //original code
            //some more logic irrelevant to the question
        }
}

The problem is in the angular.copy(). The structure of the newPeriod object is as following:

it has a "from" date and an "until" date and an array of magazine objects. Then there is the function $scope.setHolidayEditions(newPeriod). Basically it adds an array of edition objects to every magazine. This function works. I know this because of the console output. In the original code, the period is then begin pushed in an array of periods, which then is displayed on the screen. An angular.copy() was done probably to avoid reference problems.

But the angular.copy() does not seem to be copying the newly made array of editions in the magazine objects. Is there a reason for this?

Basically this is what happens in the service function:

I have an object called newPeriod, which looks about like this:

{
  from:"02/10/2015", 
  until:"09/10/2015",
  magazines: [
           {title:"some title", number:"some number", code:"magazineCode"},
           {title:"other title", number:"other number", code:"magazineCode2"}
  ]
}

after the function $scope.setHolidayEditions(newPeriod) the object looks like this:

    {
          from:"02/10/2015", 
          until:"09/10/2015",
          magazines: [
                   {title:"some title", number:"some number", code:"magazineCode", holidayEditions:["date","date","date"]},
                   {title:"other title", number:"other number", code:"magazineCode2", holidayEditions:["date","date","date"]}
          ]
}

But after the angular.copy(newPeriod), the object looks like this again:

 {
      from:"02/10/2015", 
      until:"09/10/2015",
      magazines: [
               {title:"some title", number:"some number", code:"magazineCode"},
               {title:"other title", number:"other number", code:"magazineCode2"}
      ]
    }

The angular.copy() did not copy the holidayEditions array of the magazines. And I wonder why?

like image 706
ocket-san Avatar asked Mar 15 '23 14:03

ocket-san


1 Answers

You are right and I ran into the same problem some time ago. Therefore (and also for some other reasons) I decided to use lodash which provides a function for that very issue:

_.cloneDeep(value, [customizer], [thisArg])

Creates a deep clone of value. If customizer is provided it’s invoked to produce the cloned values. If customizer returns undefined cloning is handled by the method instead. The customizer is bound to thisArg and invoked with up to three argument; (value [, index|key, object]).

Note: This method is loosely based on the structured clone algorithm. The enumerable properties of arguments objects and objects created by constructors other than Object are cloned to plain Object objects. An empty object is returned for uncloneable values such as functions, DOM nodes, Maps, Sets, and WeakMaps.

like image 53
DonJuwe Avatar answered Mar 26 '23 12:03

DonJuwe