0

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.

6
  • 1
    You might want to use Vue.set and Vue.delete as Vue doesn't have reactivity for nested objects: vuejs.org/v2/api/#Vue-set Commented Mar 3, 2019 at 19:12
  • @match How can I run a function on change with this approach though? Commented Mar 3, 2019 at 19:13
  • Just make sure that whatever changes the object uses Vue.set (rather than direct object manipulation - this will let Vue 'notice' it has changed, and your watch function will then be fired. Commented Mar 3, 2019 at 19:19
  • @match So for sex I could use something like this? Vue.set( userData, sex, male ). And would the same watcher now work? Commented Mar 3, 2019 at 19:30
  • Yes - that should allow Vue to 'see' the change. You might also want to look into Vuex as a better way of dealing with state changes. Commented Mar 3, 2019 at 19:32

2 Answers 2

2

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).

Sign up to request clarification or add additional context in comments.

2 Comments

I wasn't, let me give it a shot!
This worked, the computed I wrote was working but I didn't have the results in the page so it wasn't running!
2

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.

2 Comments

would this detect a change if I watched userData? I want to run one function for any change of the userData.
@AnthonySette I have updated the code to make this work, requires re-assigning the whole userData object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.