0

so I am splicing an array of objects, firstly to make a copy of one of the objects. This is if someone wants to "split" their order, ie make a new order of the same product but for a different shipping date.

Anyway, what I expect is, assuming the arguments passed for example, are "Daily Breads" and "Apple Streusel" that I get a second "Apple Streusel" in the array of objects, but the .text should become "Apple Streusel Additional". Instead what I am getting is two objects called "Apple Streusel Additional", instead of just one.

Relevant Part of my JSON that is being modified:

$scope.theBreadsList = [{
        category: 'Daily Breads',
        breads: [{
            text: 'Apple Streusel',
            category: 'Daily Breads',
            isDaily: true,
            price: 7.25,
            quantity: 0,
            days: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday"],
            daysNotAvailable: null,
            onMenu: true,
            canSlice: false,
            orderDates: [],
            ingredients: ["White Flour", "Honey", "Water", "Butter", "Brown Sugar", "Eggs", "Applesauce", "Apples", "White Sugar", "Yeast", "Spices", "Vanilla", "Salt"]
        },


        {
            text: 'Honey Whole Wheat',
            category: 'Daily Breads',
            isDaily: true,
            price: 5.65,
            quantity: 0,
            days: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday"],
            daysNotAvailable: null,
            onMenu: true,
            canSlice: true,
            orderDates: [],
            ingredients: ["Organic Whole Wheat Flour","Filtered Water","Honey","Yeast","Salt"],
        },

        {
            text: 'Peasant White',
            category: 'Daily Breads',
            isDaily: true,
            price: 5.65,
            quantity: 0,
            days: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday"],
            daysNotAvailable: null,
            onMenu: true,
            canSlice: true,
            orderDates: [],
            ingredients: ["Unbleached Unbromated White Flour", "Filtered Water","Honey","Yeast","Salt"]
        },

        {
            text: 'Rolls (White or Wheat)',
            category: 'Daily Breads',
            isDaily: true,
            price: 4.75,
            quantity: 0,
            days: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday"],
            daysNotAvailable: null,
            onMenu: true,
            canSlice: false,
            orderDates: []
        },

        {
            text: 'Seven Grain Crunch',
            category: 'Daily Breads',
            isDaily: true,
            price: 5.95,
            quantity: 0,
            days: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday"],
            daysNotAvailable: null,
            onMenu: true,
            canSlice: true,
            orderDates: [],
            ingredients: ["Freshly Milled Organic Whole Wheat Flour","Seven Grain Mix (Hard & Soft Wheat, Oats, Rye, Millet, Barley, Triticale)", "Filtered Water","Honey","Yeast","Salt"]
        },

        {
            text: 'Three Seed Healthy',
            category: 'Daily Breads',
            isDaily: true,
            price: 6.25,
            quantity: 0,
            days: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday"],
            daysNotAvailable: null,
            onMenu: true,
            canSlice: true,
            orderDates: [],
            ingredients: ["Organic Whole Wheat Flour","Honey","Filtered Water","Sunflower Seeds","Sesame Seeds","Flax Seeds","Yeast","Salt"]
        }]

My function:

function add2JSON(breadCategory,bread){
  for (var i = 0; i < $scope.theBreadsList.length; i++) {
                    if ($scope.theBreadsList[i].category === breadCategory) {
                      for (var z = 0; z < $scope.theBreadsList[i].breads.length; z++) {
                      if ($scope.theBreadsList[i].breads[z].text === bread) { 
                      //importante!
                      console.log(z);
                      $scope.theBreadsList[i].breads.splice(z, 0, $scope.theBreadsList[i].breads[z]);
                      console.log($scope.theBreadsList, $scope.theBreadsList[i].breads[z], $scope.theBreadsList[i].breads[z+1]);
                      $scope.theBreadsList[i].breads[z+1].text = $scope.theBreadsList[i].breads[z+1].text + " Additional";
                      $scope.theBreadsList[i].breads[z+1].onMenu = false;
                      return;
                      }
                      }
                }
            }
}

My Call:

add2JSON("Daily Breads","Apple Streusel");
Summer Developer
  • 2,056
  • 7
  • 31
  • 68
  • How to copy objects: http://stackoverflow.com/questions/728360/most-elegant-way-to-clone-a-javascript-object – trincot Nov 29 '15 at 12:34

3 Answers3

3

You are modifying object properties of an object which is referenced in both the original and modified array.

You need to deep copy the array element you insert. As you use AngularJS, you could use angular.copy for that, as follows:

Replace this line:

$scope.theBreadsList[i].breads.splice(z, 0, 
    $scope.theBreadsList[i].breads[z]);

with:

$scope.theBreadsList[i].breads.splice(z, 0,
    angular.copy($scope.theBreadsList[i].breads[z]));
trincot
  • 317,000
  • 35
  • 244
  • 286
0

I would choose a different approach. Something like:

var arr = $scope.theBreadsList; // just to ease the example  

function add2JSON(breadCategory, bread) {
  var cat = arr.filter(function(c) { return c.category === breadCategory; })[0];
  var originalBread;
  var isAdditional = cat.breads.some(function(b) {
    if (b.text === bread) {
      originalBread = b;
      return true;
    }
    return false;
  });

  if (isAdditional) {
    var newBread = Object.assign({}, originalBread, {
      text: originalBread.text + ' (Additional)'
    });
    cat.breads.push(newBread);
  } else {
    // TODO: implement the case where it not exists already
  }
}

add2JSON('Daily Breads', 'Apple Streusel');

See this working DEMO

letiagoalves
  • 11,224
  • 4
  • 40
  • 66
0

You can make a copy with

c = JSON.parse(JSON.stringify(b));

and insert it as desired.

var $scope = {};
$scope.theBreadsList = [{ category: 'Daily Breads', breads: [{ text: 'Apple Streusel', category: 'Daily Breads', isDaily: true, price: 7.25, quantity: 0, days: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday"], daysNotAvailable: null, onMenu: true, canSlice: false, orderDates: [], ingredients: ["White Flour", "Honey", "Water", "Butter", "Brown Sugar", "Eggs", "Applesauce", "Apples", "White Sugar", "Yeast", "Spices", "Vanilla", "Salt"] }, { text: 'Honey Whole Wheat', category: 'Daily Breads', isDaily: true, price: 5.65, quantity: 0, days: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday"], daysNotAvailable: null, onMenu: true, canSlice: true, orderDates: [], ingredients: ["Organic Whole Wheat Flour", "Filtered Water", "Honey", "Yeast", "Salt"], }, { text: 'Peasant White', category: 'Daily Breads', isDaily: true, price: 5.65, quantity: 0, days: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday"], daysNotAvailable: null, onMenu: true, canSlice: true, orderDates: [], ingredients: ["Unbleached Unbromated White Flour", "Filtered Water", "Honey", "Yeast", "Salt"] }, { text: 'Rolls (White or Wheat)', category: 'Daily Breads', isDaily: true, price: 4.75, quantity: 0, days: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday"], daysNotAvailable: null, onMenu: true, canSlice: false, orderDates: [] }, { text: 'Seven Grain Crunch', category: 'Daily Breads', isDaily: true, price: 5.95, quantity: 0, days: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday"], daysNotAvailable: null, onMenu: true, canSlice: true, orderDates: [], ingredients: ["Freshly Milled Organic Whole Wheat Flour", "Seven Grain Mix (Hard & Soft Wheat, Oats, Rye, Millet, Barley, Triticale)", "Filtered Water", "Honey", "Yeast", "Salt"] }, { text: 'Three Seed Healthy', category: 'Daily Breads', isDaily: true, price: 6.25, quantity: 0, days: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday"], daysNotAvailable: null, onMenu: true, canSlice: true, orderDates: [], ingredients: ["Organic Whole Wheat Flour", "Honey", "Filtered Water", "Sunflower Seeds", "Sesame Seeds", "Flax Seeds", "Yeast", "Salt"] }] }];

function add2JSON(breadCategory, bread) {
    $scope.theBreadsList.forEach(function (a) {
        var c, p;
        if (a.category === breadCategory) {
            a.breads.some(function (b, i) {
                if (b.text === bread) {
                    p = i,
                    c = JSON.parse(JSON.stringify(b));
                    c.text += " Additional";
                    c.onMenu = false;
                    return true;
                }
            }) && a.breads.splice(p, 0, c);
        }
    });
}

add2JSON("Daily Breads", "Apple Streusel");
document.write('<pre>' + JSON.stringify($scope, 0, 4) + '</pre>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392