Angular.copy() Isn't Creating An Independent Copy Of An Object
I have an AngularJS app that uses a factory to load JSON data into objects. Note that the following example is a VERY stripped down version of the real-life app. The user objects
Solution 1:
The name
and id
properties were bounded incorrectly as private properties in the User
factory, so name
could not be accessed in the view (and I assume it broke the two-way binding).
Bind them to the factory object (using this
) and it should be resolved.
angular.module('foo', [])
.controller('ctrl', function($scope, UserFactory)
{
// Maps user IDs to user objects// Using hash instead of array for fast access by ID
$scope.users = UserFactory.load();
// Maps IDs of users to copies of the respective user objects, used for editing
$scope.editUsers = {};
// Return whether or not we're editing the user
$scope.inEditMode = function(userID)
{
return $scope.editUsers.hasOwnProperty(userID);
};
// Copy the changes made to the actual user object
$scope.saveChanges = function(userID)
{
$scope.users[userID] = angular.copy($scope.editUsers[userID]);
// Don't need the edit-copy, so get rid of itdelete $scope.editUsers[userID];
};
// Turn edit mode on/off
$scope.setEditMode = function(userID, inEditMode)
{
if(inEditMode)
{
// IN THEORY, this should create two independent copies of the same object
$scope.editUsers[userID] = angular.copy($scope.users[userID]);
/**
* PROOF THESE ARE THE SAME OBJECTS:
* This shouldn't affect the edit-copy in the view, but it does
*/
$scope.users[userID].setName("WHY IS THIS THE SAME");
}
else
{
// We are effecively canceling the changes we've madedelete $scope.editUsers[userID];
}
};
})
.factory('UserFactory', function(User)
{
return {
load: function()
{
// Simulate a JSON response with user datavar rawUserData = [
{id: 1, name: "Dave"},
{id: 2, name: "Brian"}
];
var userIDsToObjects = {};
for(var userIter = 0;userIter < rawUserData.length;userIter++)
{
userIDsToObjects[rawUserData[userIter].id] = newUser(rawUserData[userIter].id, rawUserData[userIter].name);
}
return userIDsToObjects;
}
}
})
.factory('User', function()
{
returnfunction(newID, newName)
{
this.getID = function()
{
returnthis.id;
};
this.getName = function()
{
returnthis.name;
};
this.setID = function(newID)
{
this.id = +newID;
};
this.setName = function(newName)
{
this.name = newName;
};
var self = this;
// var id;// var name;
(function()
{
self.setID(newID);
self.setName(newName);
})();
}
})
.directive('ngModelGetter', function()
{
return {
require: "ngModel",
//controller: "ctrl",link: function(scope, element, attrs, ngModelCtrl)
{
var getExpression = attrs.ngModelGetter;
functionupdateViewValue(newValue, oldValue)
{
if(newValue != ngModelCtrl.$viewValue)
{
ngModelCtrl.$setViewValue(newValue);
ngModelCtrl.$render();
}
var updateExpression = attrs.ngModel + "=" + getExpression;
scope.$eval(updateExpression);
}
updateViewValue();
scope.$watch(getExpression, updateViewValue);
}
};
})
.directive('ngModelSetter', function()
{
return {
require: "ngModel",
//controller: "ctrl",link: function(scope, element, attrs, ngModelCtrl)
{
var setExpression = attrs.ngModelSetter;
functionupdateModelValue(e)
{
scope.$value = ngModelCtrl.$viewValue;
scope.$eval(setExpression);
delete scope.$value;
}
scope.$watch(attrs.ngModel, updateModelValue);
}
};
})
<scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js"></script><divng-app="foo"ng-controller="ctrl"><divng-repeat="(userID, user) in users"><spanng-if="inEditMode(userID)"><inputtype="text"ng-model="$name"ng-model-getter="editUsers[userID].getName()"ng-model-setter="editUsers[userID].setName($value)" /><buttonng-click="saveChanges(userID)">Save</button><buttonng-click="setEditMode(editUsers[userID].getID(), false)">Cancel</button></span><spanng-if="!inEditMode(userID)">
{{user.getName()}}
<buttonng-click="setEditMode(userID, true)">Edit</button></span></div></div>
Solution 2:
Looking at the source for angular.copy, if you do not specify destination, it is set to source.
if (!destination) {
destination = source;
In the end, it just:
return destination;
Post a Comment for "Angular.copy() Isn't Creating An Independent Copy Of An Object"