0

I have two data objects called items and itemsOrg

var vm = new Vue({
      el: '#divVM',
      mixins: [mix],     
      data: {
            items: [],
            itemsOrg:[],
            // ....
           },

When the page loads, I make an AJAX call to fetch data from MySQL table and assign it to items and itemsOrg object.

function getMustacheVariables()
{
    $.ajax({
       type: "POST",
       url: "adminAjax.php", 
        data: { 
            actionID: 'GET_DATA', 
        },
        dataType: "json",

        success: function(data) 
        {
            vm.items= data; 
            vm.itemsOrg = data;
        }
        // ...

However, when I update Vm.items, vm.itemsOrg is also automatically updated and don't know why these the two are linked. Here is a snapshot of console.log

vm.items[0]["key"] 
"agent"
vm.itemsOrg[0]["key"]
"agent"
vm.items[0]["key"] = "new_key"
"new_key"
vm.itemsOrg[0]["key"]
"new_key"
vm.itemsOrg[0]["key"] = "updated_key"
"updated_key"
vm.items[0]["key"] 
"updated_key"

Is there a reason that these two objects are linked? I even tried assigning vm.items to vm.itemsOrg using vm.items.slice() as well as push() but the two objects are always linked.

I appreciate any help.

user761100
  • 2,171
  • 4
  • 23
  • 31
  • 1
    you're assinging data for both. what you expect? – Bhojendra Rauniyar Aug 09 '18 at 15:32
  • There was a typo error in my original post. Please see updated code. – user761100 Aug 09 '18 at 15:34
  • i'm still seeing the same. – Bhojendra Rauniyar Aug 09 '18 at 15:34
  • 1
    `vm.items= data; vm.itemsOrg = data;` means both variables are now references to the same object. You'll want to [clone](https://stackoverflow.com/questions/30578254/does-vue-js-have-a-built-in-way-to-add-a-copy-of-a-persistent-object-to-a-repeat) `data` instead of simply assigning the other variables as equal to it. – Daniel Beck Aug 09 '18 at 15:34
  • Try using `[...data]` for arrays, or `{...data}` for objects. – m3characters Aug 09 '18 at 15:37
  • My requirements is to initially assign the same data to two objects, Later when the user updates data in vm.items, I want vm.itemsOrg to stay the same (originally loaded data) so that I may compare if user has updated any data on the page. – user761100 Aug 09 '18 at 15:37
  • What if you try: `vm.items.concat(data); vm.itemsOrg.concat(data)` ? – PaulCo Aug 09 '18 at 15:45
  • @PaulCo: contact(data) does not work as data is object. – user761100 Aug 09 '18 at 16:10
  • @m3characters: I tried vm.items= data; vm.itemsOrg = {...data}; but still when I change vm.items, vm.itemsOrg changes, – user761100 Aug 09 '18 at 16:13
  • Probably when you change an item, you'll want to spread it into a new item, so that it's not referencing the same object. so first `vm.itemsOrg = [...data]`, then when changing a specific item `vm.items[0] = {...vm.items[0], key: "test" }`, but you might be more interested in this thread, https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript/5344074#5344074 - as this is not a vuejs issue, but just how js works. In jquery, it works because you use `true`as the first param to extend, which executes a deep copy with new references. – m3characters Aug 09 '18 at 17:01
  • So it seems that `data = { 0: {key: 'agent'})`, if you're declaring `vm.items = []` and then putting `vm.items = data` you are shifting from a table to an object... If data is indeed an [Array-like Object](https://stackoverflow.com/questions/29707568/javascript-difference-between-array-and-array-like-object) then you could try `vm.items = Array.from(data)` in ES6 – PaulCo Aug 10 '18 at 08:34

2 Answers2

3

After playing with your example I noticed that we can simplify your AJAX fetched object as data = { 0: { key: 'agent'} and it has this property data[0] assigned to a reference of the object { key: 'agent'} (data can be called a nested object)

So it seems that even if you're copying the data object with Object.assign you'll still have every referenced object in it. As said here :

But be aware that this makes a shallow copy only. Nested objects are still copied as references.

So you have two options that would work without JQuery:

1. Using JSON.parse and JSON.stringify like JSON.parse(JSON.stringify(data)) to stringify then parse your object

2. Making a loop to manually deep copy the object (as in the outdated answer of the thread referenced above)

And if using JQuery you can write jQuery.extend(true ,{}, data) with the deep option set to true

PaulCo
  • 1,398
  • 4
  • 17
  • 31
1

Yes there is a reason here. this code means that's vm.items and vm.itemsOrg are the same ref (data).

use chrome devtools to see the Trace

    vm.items= data; 
    vm.itemsOrg = data;