Grandizer
Grandizer

Reputation: 3025

Why Is Vue Data Element Changing When I Only Set It Once?

I have created a component that allows users to select objects from a list and put them into another "selected list" lets say. So there are 100 items in the main list and however many in the users selected list. They can of course remove and add items as they want.

There are two buttons at the bottom of the modal. Cancel and Update. Where Cancel forgets anything they have added or removed (essentially an Undo of when they popped up the modal) and Update technically does nothing because when you are adding and removing, I am actually updating the real selected list.

So my data has these two properties (among others of course):

originalSelections: [],
selectedMedications: [],

There is a method that only gets called one time to set the selectedMedications property to whatever the current state of originalSelections is. I have a console.log to prove I am not running this method more than once and it NEVER gets hit again.

console.log('Post Initing');

let Selected = [];

for (let med of this.value.OtherNotFromEpic) {
  let match = this.otherMedications.find(x => { return x.value === med });

  if (match) {
    Selected.push(JSON.parse(JSON.stringify(match)));
    this.originalSelections.push(JSON.parse(JSON.stringify(match)));
    this.selectedMedications.push(JSON.parse(JSON.stringify(match)));
  }
}

I was baffled at why the selectedMedications was changing, so I added a watch to let me know if it was:

watch: {
  originalSelections(newValue) {
    console.log(' ** Original Selection Changed', this.init, newValue);
  },
},

The Cancel method is as follows:

cancel() {
  $('#' + this.modalID).modal('hide');
  console.log('Cancel: this.originalSelections', JSON.parse(JSON.stringify(this.originalSelections)));

  this.selectedMedications = this.originalSelections;

  this.$nextTick(() => {
    console.log('  Cancelled: this.selectedMedications', JSON.parse(JSON.stringify(this.selectedMedications)));
  });
},

You can see that I am setting selectedMedications to whatever it was originally.

The odd thing is... This WORKS 100% the first time I bring up the modal. So I pop up the modal, remove an item, cancel the modal and it brings back the item I removed. Perfect!

If I bring the modal up again, remove that same item or any other item, cancel the modal and that item stays removed and the watch is actually hit. I have NO other place in the code where originalMedications = … or originalMedications.push or even originalMedications.slice ever happen. And it is my understand that the JSON.parse(JSON.stringify(match)) code I use to set it is making a new object and not a reference in any way.

Another odd thing I have found is that if I refresh the page, open the modal, cancel out without doing any adding or removing. Then I bring up the modal again and try either add or remove, then cancel the modal, those items do not revert back to the originalMedications state because originalMedications is the same as selectedMedications. Aargh!

So HOW can a property get altered when I never do anything to it after the initial setting of it?

Upvotes: 1

Views: 61

Answers (1)

Gowri
Gowri

Reputation: 394

In the cancel method, when below direct assignment is done here after both data is referring to same (since its array). So any time after the first cancel both originalSelections and selectedMedications array would have same reference and hence same data.

this.selectedMedications = this.originalSelections;

instead better to use concat as below? This will create a copy of originalSelections and assign that to selectedMedications. So any operations on selectedMedications will not affect the originalSelections.

this.selectedMedications = [].concat(this.originalSelections);

Upvotes: 1

Related Questions