Anthony Sette
Anthony Sette

Reputation: 837

How do you run a function when any data in an object is changed using Vuejs?

So I have the following data, and my goal is to recalculate the user's results every time data in this object is changed. Here is the data.

data() {
  return {     
    test: 0, 
    userData: {
      sex: null,
      age: null,
      feet: null,
      inches: null,
      activity: null,
      goal: null,
    },
  }
}

Now I have tried to implement both watch and computed, but it seams Vue is not noticing when individual items in the object are changed. However, if I take some data out of the object it does notice the change.

Here is what I tried for watch:

watch: {
  userData: function () {
    console.log("Changed");
  }
}

The result was nothing in the console.

For computed I tried the following:

computed: {
  results: function () {
    console.log(this.userData);
    return this.userData.sex;
  }
}

But again nothing was printed in the console.

If I tried with the test variable:

watch: {
  test: function () {
    console.log("Changed");
  }
}

It WOULD output changed when the variable was changed. So that works because it is not an object.

Any help would be very appreciated. Again the goal is to recalculate results whenever any userData is changed.

Upvotes: 0

Views: 1318

Answers (2)

jaredrethman
jaredrethman

Reputation: 511

Here is one way to do it. You need (as @match mentioned) use Vue.set() or vm.$set(). I found it was also necessary to update your watcher property to userData.sex.

new Vue({
  el: "#app",
  data: {  
    status: '', 
    userData: {
      sex: ''
    },
  },
  methods: {
    updateValues(){
      // Or Vue.set()
      this.$nextTick( function(){
        const newUserData = Object.assign({}, this.userData);
        newUserData.sex = "Male";
        this.userData = newUserData;
      });
    }
  },
  watch: {
    userData: function (v) {
      this.status += "userData Changed";
    },
    'userData.sex': function (v) {
      this.status += "\nuserData.sex Changed";
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<div id="app">
  <pre v-text="'userData.sex = ' + userData.sex"></pre>
  <pre v-text="status"></pre>
  <button @click="updateValues()">
    Change Sex
  </button>
</div>

EDIT:

Re-assigning the whole object, userData, triggers the watch.userData.

Upvotes: 2

Phil
Phil

Reputation: 795

Are you actually using the results property (in your template for example)? Computed properties do not get recomputed if they are not being used.

As opposed to what @match says, I doubt you have a reactivity problem since you do not add or delete properties (they already exist in your data so they are already reactive).

Upvotes: 2

Related Questions