更改范围变量更新服务变量

时间:2016-10-15 12:41:57

标签: angularjs

有人可以看看下面的plunker吗?

http://plnkr.co/edit/oTHJcVVzJE5CwMnFMEpS?p=preview

问题:更改范围变量“specifications.selectedColor”会覆盖其他产品的规格,即更改所有产品的selectedColor。

重现的步骤: 1)点击立即购买。 checkoutProductList [0] .selectedColor设置为Red。 2)从下拉列表中选择蓝色。 3)点击立即购买。 checkoutProductList [0] .selectedColor设置为Blue。

点击第二次立即购买(上面的第3步),它在checkoutProductList数组中添加另一个产品,即checkoutProductList [1],它不应该改变 checkoutProductList [0] .selectedColor从Red到Blue。

如何分别保持每种产品的规格?

代码: 位指示

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="angular.js@1.4.x" 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>

1 个答案:

答案 0 :(得分:1)

<强>问题

问题在于JavaScript中的深层复制和浅层复制。当您将对象推送到数组时,它并没有真正创建对象的副本而是推送它而只是存储对原始对象的引用(在您的情况下为$ scope.specifications)。由于您要更改控制器中的$ scope.specifications对象,因此阵列也会发生变化。

<强>解决方案

您可以利用angular.copy方法,该方法用于创建对象的深层副本。所以你可以做的是在将对象推送到数组之前,你可以制作一个对象的深层副本,然后将它推送到数组。

在您将对象推送到阵列的服务中进行此更改

checkoutProductList.push(angular.copy(specs));

全程服务

app.service ('checkoutService', function (){
    var checkoutProductList=[];
    this.setCheckoutProductList = function ( specs){
    checkoutProductList.push(angular.copy(specs));
    window.alert(checkoutProductList.length);
    window.alert(JSON.stringify(checkoutProductList));
 }

我还创建了一个plunkr来演示工作解决方案。你可以看到它here

相关问题