Reputation: 23
Can somebody please have a look at below plunker?
http://plnkr.co/edit/oTHJcVVzJE5CwMnFMEpS?p=preview
Problem: Change in the scope variable "specifications.selectedColor" is overwriting the specifications of other products i.e changing the selectedColor of all the products.
Steps to reproduce: 1) Click on Buy Now. checkoutProductList[0].selectedColor is set to Red. 2) Select Blue color from the drop-down. 3) Click on Buy Now. checkoutProductList[0].selectedColor is set to Blue.
On clicking Buy Now second time(step 3 above), it adds another product in checkoutProductList Array i.e checkoutProductList[1], it should not change checkoutProductList[0].selectedColor from Red to Blue.
What can be done to keep specifications of each product separately?
Code: Contoller
var app = angular.module('plunker', ['ui.select', 'ngSanitize']);
app.controller('MainCtrl', function($rootScope, $scope,checkoutService) {
$scope.productAvailableColors=['Red','Blue'];
$scope.specifications={'selectedColor':'Red'};
$scope.buyNow = function (){
checkoutService.setCheckoutProductList($scope.specifications);
};
});
app.service ('checkoutService', function (){
var checkoutProductList=[];
this.setCheckoutProductList = function ( specs){
checkoutProductList.push(specs);
window.alert(checkoutProductList.length);
window.alert(checkoutProductList[0].selectedColor);
}
})
HEAD
HTML:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="[email protected]" src="https://code.angularjs.org/1.4.12/angular.js" data-semver="1.4.9"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.3/css/bootstrap.min.css" integrity="sha384-MIwDKRSSImVFAZCVLtU0LMDdON6KVCrZHyVQQj6e8wIEJkW4tvwqXrbMIya1vriY" crossorigin="anonymous">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js" integrity="sha384-THPy051/pYDQGanwU6poAc/hOdQxjnOEXzbT+OuUAFqNqFjL+4IGLBgCJC3ZOShY" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.2.0/js/tether.min.js" integrity="sha384-Plbmg8JY28KFelvJVai01l8WyZzrYWG825m+cZ0eDDS1f7d/js6ikvy1+X+guPIB" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.3/js/bootstrap.min.js" integrity="sha384-ux8v3A6CPtOTqOzMKiuo3d/DomGaaClxFYdCu2HPMBEkf6x2xiDyJ7gkXU0MWwaD" crossorigin="anonymous"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.12/angular-sanitize.js"></script>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/select2/3.4.5/select2.css">
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.8.5/css/selectize.default.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.19.4/select.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.19.4/select.min.css">
<script src="app.js"></script>
</head>
BODY
<body ng-controller="MainCtrl">
<div class="productModal-circle"
style="cursor: pointer; font-size: 14px; "
aria-hidden="true"
ng-click="buyNow()"
title="Buy Now!" id="buyNow">Buy Now
</div>
<div id="choices" class="panel-collapse collapse in">
<div class="panel-body">
<ui-select ng-model="$parent.specifications.selectedColor"
theme="bootstrap"
ng-disabled="false"
close-on-select="true"
style="color: black;"
title="Choose Color and Design"
>
<ui-select-match placeholder="Choose Color/Design">{{$parent.specifications.selectedColor}}</ui-select-match>
<ui-select-choices repeat="listItem in productAvailableColors | filter:$select.search">
<div ng-bind-html="listItem | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
</div>
</div>
{{specifications | json}}
</body>
</html>
Upvotes: 1
Views: 460
Reputation: 3746
Problem
The problem lies in deep copy and shallow copy in JavaScript. When you are pushing an object to the array, it's not really creating a copy of the object and pushing it instead it just stores a reference to the original object (which is $scope.specifications in your case). Since you are changing the $scope.specifications object in your controller your array is also getting changed.
Solution
You can leverage the angular.copy method which is used to create deep copy of an object. So what you can do is before pushing the object to the array, you can make a deep copy of the object and then push it to the array.
In your service where you are pushing the object to the array make this change
checkoutProductList.push(angular.copy(specs));
Full Service
app.service ('checkoutService', function (){
var checkoutProductList=[];
this.setCheckoutProductList = function ( specs){
checkoutProductList.push(angular.copy(specs));
window.alert(checkoutProductList.length);
window.alert(JSON.stringify(checkoutProductList));
}
I have also created a plunkr to demonstrate the working solution. You can see it here.
Upvotes: 1