0

I've got an object which has one property with arrays:

$scope.orderContent ={} $scope.orderContent.products = []

Then I have a function that on click will push an object into the array:

if ($scope.orderContent.products.length) {

        angular.forEach($scope.orderContent.products, function (iIndex, oValue) {

            if (prod.id === iIndex.id) {

                iIndex.qty ++;

            } else if (prod.id !== iIndex.id) {

                prod.subcategory = subcat.name;
                prod.category = category.name;
                prod.qty = 1;
                $scope.orderContent.products.push(prod);

            }

        });

    } else if (!$scope.orderContent.products.length || $scope.orderContent.products.length === 0) {

        prod.subcategory = subcat.name;
        prod.category = category.name;
        prod.qty = 1;
        $scope.orderContent.products.push(prod);

    }

on the template I've got three nested hg-repeat. The object which is used to loop through looks roughly like this: category = {}; category.subcategories = {}; category.subcategories.products = {} so my template loops through each layer (category, subcategory, product) to display each product.

I attach the aforementioned function on the product like so:

<button ng-click="addProduct(product, subcategory, category)">

What I don't understand is this: when I click on the same product twice, the above code works as expected. Instead of pushing the same object twice it'll simply change the quantity property of the product object. If I click on a secondary product, it will push another object into the array. So far so good. The problem happens when click on the secondary product for the second time. The product object in question will have its quantity increased as well as having the object being pushed into the array. By then I get an error saying that "Duplicates in a repeater are not allowed".

So I'm wondering is there a delay (on Angular's part) due to the two way binding or I doing something stupid and can't see? I've been struggling with this on and off for almost two weeks and can't seen to find a solution.

Can anyone please enlighten me?

Many thanks

WagnerMatosUK
  • 4,309
  • 7
  • 56
  • 95
  • possible duplicate of [Angular ng-repeat Error "Duplicates in a repeater are not allowed."](http://stackoverflow.com/questions/16296670/angular-ng-repeat-error-duplicates-in-a-repeater-are-not-allowed) – shaunhusain Mar 15 '14 at 18:03
  • Hi voted to close, you laid out the question well but I think the root problem is just to do with the "duplicates" for which the problem and solution are described in the link above. – shaunhusain Mar 15 '14 at 18:04
  • The problem isn't really the duplicates error generated by angular, but the fact that he gets the duplicates in the array in the first place (instead of just having the qty increased), right? – Miichi Mar 15 '14 at 18:21
  • @shaunhusain Hi. well, I don't think is a duplicate because in my case, I can see why it is repeating but I don't want it to repeat. In the above code, my intention was to check whether the object is already in the array, if it was, update it. If it isn't, push the object into the array. The duplicate error is a byproduct/error that I can't seen to find the solution for. I don't know whether is my mistake (probably) or some bug (much less likely I'd say) in Angular – WagnerMatosUK Mar 15 '14 at 18:22
  • @Miichi that's right! I don't want it to duplicate but I can't see what I am doing wrong. – WagnerMatosUK Mar 15 '14 at 18:24
  • gotcha retracted my vote to close, good luck, looks like there's an answer for ya – shaunhusain Mar 15 '14 at 18:28

1 Answers1

0

Think the issue is your for-loop logic -- in the else if part you are basically pushing a new entry to the end of the array for each other product, i.e., each entry in the array where prod.id !== iIndex.id. Instead move the push outside of the loop like this:

    var found = false;
    angular.forEach($scope.orderContent.products, function (iIndex, oValue) {
        if (prod.id === iIndex.id) {
            found = true;
            iIndex.qty ++;
        }
    }
    if(!found) {
        prod.subcategory = subcat.name;
        prod.category = category.name;
        prod.qty = 1;
        $scope.orderContent.products.push(prod);
    }

Event better, use a function like find on your array.

Miichi
  • 1,739
  • 1
  • 14
  • 16
  • It worked like a charm! Thank you! PS +1 for the simplicity! I had loops, conditionals, etc. You made it much more elegant :) – WagnerMatosUK Mar 15 '14 at 18:34
  • Be careful though that `find` is available only in Firefox (I didn't read the fine print on the linked page). However, libraries like underscore, lodash, etc. provide similar functionality. – Miichi Mar 15 '14 at 18:38
  • I ended up not using `find`, opted for the loop instead. I did see find wasn't available on other browsers so thought better sit it out. Looks promising though :) – WagnerMatosUK Mar 15 '14 at 19:06