Home » vue » Problem with Child value from Vue component changing Parent value

Problem with Child value from Vue component changing Parent value

Posted by: admin November 26, 2021 Leave a comment

Questions:

I have an Array that I use to populate a Dialog Vue Component. I have:

           basicInfo: [{ firstName: "John" , lastName: "Doe" }],

          <basicInfoForm v-model="showBasicInfoForm" :basicInfo="newbasicInfo[0]"></basicInfoForm>

on the Parent I have

       {{basicInfo[0].firstName + ' ' + basicInfo[0].lastName}}

I have a button that will call a Form Component and open a Dialog popup that allows editing. My problem is that all changes to the Dialog are also immediately shown on the Parent. I would like to have on the Child Dialog a cancel button so no changes will be made. I cloned the array before I pass it:

       this.newbasicInfo = this.basicInfo.slice();

and on the Child Dialog

      <v-text-field
      v-model="basicInfo.firstName"
      label="First Name"
      class="input-name styled-input"
       ></v-text-field> 

      props: {
      value: Boolean,
      basicInfo: Array
      },

My problem is that I can see each key stroke as changes are being made so there is no way to go back to the original if a cancel is selected. I’m new to Vue and Components so I could have something totally screwed up. Why are changes being make to both the basicInfo array and the newbasicInfo array at the same time.

Answers:

What is happening here is that you are copying the array by reference. So when you modify the index of one array, actually both are modified because they share the same reference.
What you need to do is to copy the array by values.

this can be easily done this way : this.newbasicInfo = JSON.parse(JSON.stringify(this.basicInfo));

You can check this question on SO for more context : How do you clone an Array of Objects in Javascript?

###

Your clone method does not work with an array of objects:

const basicInfo = [{ firstName: "John" , lastName: "Doe" }]
const newbasicInfo = basicInfo.slice()

This method creates a “shallow copy” – that means it works with numbers, strings, etc. but does not really create a clone of objects. The cloned objects this way keep their reference, so they will actually be the “same” objects as in the source array.

const basicInfo = [{ firstName: "John" , lastName: "Doe" }]
const newbasicInfo = JSON.parse(JSON.stringify(basicInfo))

This method creates a “deep copy” – everything it holds will be cloned, no matter how “deep” they are nested.

If you have an array of simple values, the shallow copy is more efficient, but if you have objects in your array you need deep copy.

So, it’s not a Vue problem, but a more general JavaScript question.

Here’s a little snippet, to illustrate the difference:

const basicInfo1 = [{
  firstName: "John",
  lastName: "Doe"
}]
const newbasicInfo1 = basicInfo1.slice()

newbasicInfo1[0].firstName = "Johnnyboy"
console.log('basicInfo1: ', basicInfo1)
console.log('newbasicInfo1: ', newbasicInfo1)



const basicInfo2 = [{
  firstName: "John",
  lastName: "Doe"
}]
const newbasicInfo2 = JSON.parse(JSON.stringify(basicInfo2))

newbasicInfo2[0].firstName = "Johnnyboy"
console.log('basicInfo2: ', basicInfo2)
console.log('newbasicInfo2: ', newbasicInfo2)