Hello I am beginner in Vue and I do have a problem that's really bugging me. I am wondering should we use v-model directive to modify vuex store? Vuex says that we should modify vuex store only by mutations but v-model makes everything easier and shorter.(I am asking because i couldn't find clear answer)
https://vuex.vuejs.org/guide/forms.html
When using Vuex in strict mode, it could be a bit tricky to use
v-model
on a piece of state that belongs to Vuex.The "Vuex way" to deal with it is binding the
<input>
's value and call an action on the input or change event.
Be sure to check out the simple "Two-way Computed Property" example on that page:
<input v-model="message"> computed: { message: { get () { return this.$store.state.obj.message }, set (value) { this.$store.commit('updateMessage', value) } } }
I think another good option which hasn't been mentioned in any answer here is to use vuex-map-fields. In fact, the library author has written a very nice explanation for the library's usefulness. As per its GitHub page, to use the library you can do something like this:
In your Vuex Store, you can have a snippet similar to this:
import Vue from 'vue';
import Vuex from 'vuex';
import { getField, updateField } from 'vuex-map-fields';
Vue.use(Vuex);
export default new Vuex.Store({
// ...
modules: {
fooModule: {
namespaced: true,
state: {
foo: '',
},
getters: {
getField,
},
mutations: {
updateField,
},
},
},
});
And in your component code, you can have something along the lines of this:
<template>
<div id="app">
<input v-model="foo">
</div>
</template>
<script>
import { mapFields } from 'vuex-map-fields';
export default {
computed: {
// `fooModule` is the name of the Vuex module.
...mapFields('fooModule', ['foo']),
},
};
</script>
Additional examples for various use cases are shown in the library's GitHub repository that I linked to in the first sentence of this answer.
Above solution can also implemented with mutations:
<template>
<input v-model="message">
</template>
<script>
import { mapMutations, mapState } from 'vuex';
export default {
computed: {
...mapState({messageFromStore: 'message'}),
message: {
get() {
return this.messageFromStore;
},
set(value) {
this.updateMessage(value);
}
}
},
methods: {
...mapMutations('updateMessage')
}
};
</script>
<input v-model="tab">
on line 2 –
Sepalous My Solution to this was to use a getter to set value
and @input
to call the mutation.
<input
type="text"
:value="$store.getters.apartmentStreet"
@input="value => $store.commit('apartmentValue', { handle: 'street', value })"
>
getters.js:
export default {
apartmentStreet: state => state.apartment.street,
};
mutations.js
export default {
apartmentValue(state, payload) {
let oldValue = state.apartment[payload.handle];
let newValue = payload.value;
if (newValue !== oldValue) state.apartment[payload.handle] = payload.value;
}
};
If you use this method be sure to check which event you want.
I use this solution.
data() {
return {
formData: {
username: '',
email: '',
bio: {
firstName: '',
lastName: ''
},
games: ['civ4', 'caesar3', 'homeworld', 'cataclysm'],
}
}
},
computed: {
...mapGetters({ //or mapState
user: 'users'
})
},
watch: {
user(newValue) {
this.formData.username = newValue.name;
this.formData.email = newValue.email;
this.formData.bio.firstName = newValue.bio.firstName;
this.formData.bio.lastName = newValue.bio.lastName;
this.formData.games = newValue.games.map(x=> { return x });
}
},
beforeCreate: fucntion() {
this.$store.dispatch('getUser');
}
And then you just regularly use v-model. It is important to make deep copy of object from store, like using map for array, and how i did stuff with object inside.
And, also you need to have initiated this user object in store also, with empty fields.
Using getter and setter in computed properties works perfect. However in my case I have 'Reset' button which should revert back all unsaved changes. I have used watcher in combination with mapState:
<h5>Edit User</h5>
...
<q-input v-model="user_data.full_name" label="Full Name" />
<q-input v-model="user_data.email" type="email" label="Email" />
<q-checkbox v-model="user_data.is_active" label="Is Active" />
...
<q-btn label="Cancel" @click="cancel" />
<q-btn label="Reset" @click="reset" />
<q-btn label="Save" @click="save" />
</template>
<script>
import { mapActions, mapState } from "vuex";
export default {
data() {
return {
id: "",
user_data: {},
};
},
computed: {
...mapState(["user"]),
},
watch: {
user(value) {
this.user_data = { ...value }; // very important to copy object
},
},
mounted() {
this.id = parseInt(this.$route.params.id);
this.getUserById({ id: this.id });
},
methods: {
...mapActions(["saveUser", "getUserById"]),
save() {
this.saveUser(this.user_data);
this.$router.push({ name: "userList" });
},
reset() {
this.user_data = this.user;
},
cancel() {
this.reset();
this.$router.push({ name: "userList" });
},
},
};
</script>
Yes you can but is not the best practice.
As the documentation say the state should be updated only inside mutation to keep the control over the state.
But if you really want to do it you can with:
v-model="$store.state.yourProperty"
© 2022 - 2024 — McMap. All rights reserved.