Why should I use angular.copy in my factory?

I am trying to get Thing factory to make an HTTP request and be able to use the response in my controller.

  • In my factory, I need to do angular.copy(data, arr) . Just doing arr = data doesn't work. Why is this? angular.copy() just a) removes everything from arr and b) iterates through data and assigns material to arr . The only difference between this and arr = data is that arr points to data , not a new copy of data . Why is it important? And why does arr = data.slice(0) not work (from what I understand, it is almost the same as angular.copy) ?

  • What is the best way to achieve my goal? (use factory correctly)

main.html

 <div class="container"> <div class="page-header"> <h1>Test App</h1> </div> <ul> <li ng-repeat="thing in things">{{thing.name}}</li> </ul> </div> 

main.controller.js

 'use strict'; angular.module('testApp') .factory('Thing', function($http) { var arr = []; return { things: arr, get: function() { $http.get('/api/things').success(function(data) { angular.copy(data, arr); // this works // arr = data; but this doesn't // arr = data.slice(0); and neither does this }); } }; }) .controller('MainCtrl', function ($scope, Thing) { Thing.get(); $scope.things = Thing.things; }); 
+5
source share
2 answers

Your problem is not related to angular, but to Javascript.

 var arr = [] // arr is a pointer to an empty array var things = arr // things is a pointer to the same empty array arr = data // now arr points to data, but things still points to the empty array 

You can verify this by running the following code:

 var a = [1]; var b = a; a = [2]; // Now if you console.log a and b, a === [2] and b === [1] 

However, if you are manipulating a property of an object

 var a = { data: 1 } var b = a; a.data = 2; // Now a.data and b.data are the same: 2 a = { data: 3 }; // Here we changed a, not its property, so a and b are not the same anymore // a.data === 3 but b.data === 2 

If you understand this, there are many ways to solve your problem, for example:

 angular.module('testApp') .factory('Thing', function($http) { var obj = {}; return { things: obj, get: function() { $http.get('/api/things').success(function(data) { obj.data = data; }); } }; }) 

And in your HTML use things.data .

Or if you do not want to use the property of the object, but the array itself, instead of replacing the pointer, you only need to update the contents of the array (so that arr still points to the same array):

 angular.module('testApp') .factory('Thing', function($http) { var arr= []; return { things: arr, get: function() { $http.get('/api/things').success(function(data) { for (var i in data) { arr[i] = data[i]; } }); } }; }) 
+7
source

This is because you are installing arr in some new array instance instead of the current one. Here is an analogy with what you are doing:

 var foo = function() { this.test = 'hello'; console.log(this.test); }; foo = function() { this.test = 'other'; console.log(this.test); }; console.log(foo()); // outputs other 

angular.copy instead does something like this:

 // foreach item in the source (in this case data) arr.push({ my: "value" }); 
0
source

Source: https://habr.com/ru/post/1212853/


All Articles