Home > Mobile >  changing model property value is changing the same property in other object
changing model property value is changing the same property in other object

Time:08-26

im new to vue , i want user to be able to add some specific social media links to the page and edit some properties like it's text

i have 2 objects in my data , models and defaults

defaults contains selectable option for social media links and their initial values

basically i copy the default value into models and let the user customize the model via inputs

 data () {
      return  {

            models : [] ,
            defaults : {

                twitter : { id : null , placeholder : 'my twitter' , icon : 'twitter'  , text : null  , 'link' : null } ,
                instagram   : { id : null , placeholder : 'my instagram'  , icon : 'instagram' , text : null  , 'link' : null } ,
                tiktok   : { id : null , placeholder : 'my tiktok'  , icon : 'tiktok' , text : null  , 'link' : null } ,

            } ,
      }
    } ,     

so there a select menu for user to select which social he wants to add to the page

Select : 
<ul >
  <li v-for="(social, index ) in defaults" :key="index"> 
     <a @click="appendSocial(index)">
       {{ index }}
     </a> 
  </li>
</ul>

here is my @click="appendSocial(index)" function

appendSocial(type){
    let typedefault = this.defaults[type];
    this.models.push(typedefault)
},

and finally i show my models to user and provide an input for editing it's text via v-model

<div v-for="(model, index) in models" v-bind:key="model.id">

    <a >
        {{ model.text === null ? model.placeholder : model.text }}
    </a>
   
    <label>Text</label>
    <input type="text"   v-model="model.text"  :key="index" :placeholder="model.placeholder">

</div>

so here is the problem , for some reason changing the models properties will change the same property in defaults ... and changing defaults properties will change the same property models !!

like if i add a twitter menu to the page and change it's text (model.text) to abc via v-model ... it will also change defaults.twitter.text to abc

to better demonstrate the problem i've added some console log to my appendSocialfunction

    appendSocial(type){
        let typedefault = this.defaults[type];
        console.log(`-------- default object for ${type} -----------`);
        console.log(typedefault);
        this.addElement(typedefault);
    },

here is the result

enter image description here

1 - i've selected a twitter link and added to my models , you can see defaults.twitter.text is null

2 - i've change my model.text (i suppose it would be models[0].text) to abc

3 - i've added another twitter link to my page ... this time defaults.twitter.text is also abc

also changing defaults properties will effect all the models the has been getting their value from that default object

like if i change the defaults.instagram.text to xyz all my models which have got their initial values from defaults.instagram will also change their text to xyz

it's like they are referencing each other , but i haven't passed the value between 2 objects by reference

im not sure what's happening here and how can i prevent this ?

CodePudding user response:

This is because

    let typedefault = this.defaults[type];
    this.models.push(typedefault)

Is storing the reference to the object into your this.models array. And so if you mutate the element, you're by default changing the base object. A quick and dirty way of doing a deep clone is the following.

let typedefault = this.defaults[type];
let clonedObj = JSON.parse(JSON.stringify(typedefault));
this.models.push(clonedObj)

Note: Lodash library does have a proper deep clone functionality. https://www.geeksforgeeks.org/lodash-_-clonedeep-method/

  • Related