1
votes

I have the following scenario:

Component Textfield:

<v-text-field
  v-model="form.profile.mobile_business"
  label="Mobile"
  prepend-inner-icon="mdi-cellphone"
></v-text-field>

I get the current value via:

data() {
        return {
            form: {
                profile: JSON.parse(JSON.stringify(this.$store.getters["user/Profile"])),
            },
        };
    },

I have a submit button that calls this method:

updateUserProfile() {
            this.$store.dispatch("user/updateProfile", this.form.profile);
        }

Everything works perfect. On my store dispatch I make the API call and update the store via my mutation:

context.commit('UPDATE_PROFILE', profile);

No errors until this step.

But if I change the form input again - after I pressed the submit button, I get:

vuex: do not mutate vuex store state outside mutation

But I don't want to change the vuex store just when I change the value on my form input. It should only be updated if someone hits the submit button.

2

2 Answers

0
votes

v-model provides 2-way data binding. Changing anything in the view will automatically attempt to update the model directly, rather than through a mutation. Thankfully, Vue allows get and set on computed properties to help us past that.

What you should do on your textfield component is add a computed property with get and set methods. It will look something like this:

computed: {
  userProfile: {
    get() {
      JSON.parse(JSON.stringify(this.$store.getters["user/Profile"]));
    },
    set() {
      // only commit the changes to the form, do not submit the action that calls the API here. 
      this.$store.commit("user/updateProfile", this.form.profile) 
    }
}

Your v-model attribute should then be set to this newly created property, and any 'set' operations (read: a user changing the input value) will call the action as opposed to attempting to set the value in the Store directly.

Here is a live example: CodePen

0
votes

I solved it this way:

form: {
    profile: _.cloneDeep(this.$store.getters['user/Profile'])
  },

and added a watch handler:

form: {
            handler: _.debounce(function (form) {
                console.log("watch fired");
            }, 500), deep: true
        }

so if the user changes the value, nothing happens (except my console.log action). if he presses the submit button, the store dispatch action will be fired.