0

My javascript/angular code is performing contrary to what i expect and i can't figure out why. I have an angular service defining two methods for getting and setting items

app.factory('orderItems',['Restangular','$mdDialog',function(Restangular,$mdDialog){
    var orderItems = [];

    return{
        getOrderItems: function(){
            return orderItems
        },


        setOrderItems: function(item,fillings){
            ...
            orderItems.push(item)
            ...

        }, ...

Items are set using ng-click and passing an item and checked addons; product_template.html

<div >

    <md-button class="md-raised" ng-click="showAddons($event,product)">Add to Cart</md-button>

    </div>

controller

app.controller('productCtrl',['$scope','getProducts','orderItems','Restangular','$mdDialog',function($scope,getProducts,orderItems,Restangular,$mdDialog){
    //$scope.products;
    $scope.products = getProducts(Restangular);

    // Dialog
    $scope.showAddons=function(ev,product){
    $mdDialog.show({
        locals:{current_Product: product,},
        //inline controller
        controller:['$scope','current_Product','orderItems',function($scope,current_Product,orderItems){
        $scope.product = current_Product;
        $scope.addons = {
        checked:[],}
        ...
        }],
        templateUrl: 'dialog.html',
        targetEvent: ev, 
    })
    }

}])

dialog.html

<md-list-item ng-repeat="addon in product.productAddons">
...
<md-checkbox class="md-secondary" checklist-model="addons.checked" checklist-value="addon"></md-checkbox>
</md-list-item>
  <md-button class="md-raised" style="background-color:#f44336; color:#fff" ng-click="setOrderItems(product,addons.checked)">Done</md-button>

The problem arises when setOrderItems is passed a similar object more than once. The first time around, orderItems.push works as expected then when a similar product is passed to 'setOrderItems', it is pushed to 'orderItems' but all items in 'orderItems' are updated to this currently set item.

That is, if orderItems was[{name:"chicken burrito",fillings:[{name:"cabbage"},{name:"cheese"}],...}] before, after setting a similar item but with diff fillings, orderItems is updated to [{name:"chicken burrito",filling:[{name:"guac"}],...},{name:"chicken burrito",filling:[{name:"guac"}],...}] . If setOrderItems is passed a different product say [{name:"goat burrito",...}] it is added as expected.

Can't happen to find a similar issue around. What am i doing wrong. I want to be able to add similar items but with different fillings to orderItems.

Suziemac Tani
  • 455
  • 9
  • 23
  • The obvious answer is that you aren't pushing a *new* object, you are pushing the *same* object into the array twice. What you probably need to do is, after pushing an object onto the array, create a *new* object to replace it in the current scope. – Matt Burland Jun 09 '15 at 13:57
  • @Matt, do you think could explain yourself in a complete answer, my JavaScript is not good. I would appreciate a good explanation if its no bother. – Suziemac Tani Jun 09 '15 at 14:02

1 Answers1

4

It's difficult to see exactly with the code you've given. But if I'm following what you are doing correctly, then the problem is probably here:

$scope.products = getProducts(Restangular);

you are getting a set of products, I assume that there is an object for chicken burrito and an object for goat burrito. The problem, I think, is that you are using the same object for every chicken burrito. So when you push it onto the array you are pushing a reference to the object in products, you then edit that object and push it again. But again you are pushing a reference to the same object. If you actually look at your array before the second push, I suspect you will see that the object already on the array is already altered to match the one you are about to push because it's the same object.

To solve this, you need to make a copy of the object. To do that, take a look at this question:

Deep copying objects in angular?

angular.copy should let you copy your product so that you aren't always pushing the same object.

For example, you could do this:

setOrderItems: function(item,fillings){
    ...
    var itemCopy = angular.copy(item);
    orderItems.push(itemCopy);
    ...
}

Now you are always pushing a copy into your array and your array will fill with independent objects.

Community
  • 1
  • 1
Matt Burland
  • 44,552
  • 18
  • 99
  • 171