Update data using vuex
Solution 1
You can wrap your parameters in 1 payload
object:
In your component
this.$store.dispatch('updateCategory', {
id: this.$route.params.id,
data: this.category
});
in your store, you need to made new object when edit categories
array (you can read more about immutable)
const state = {
categories: []
};
//mutations:
[mutationType.UPDATE_CATEGORY] (state, payload) {
state.categories = state.categories.map(category => {
if (category.id === payload.id) {
return Object.assign({}, category, payload.data)
}
return category
})
}
//actions:
updateCategory({commit}, payload) {
categoriesApi.updateCategory(payload.id, payload.data).then((response) => {
commit(mutationType.UPDATE_CATEGORY, payload);
router.push({name: 'categories'});
})
}
Solution 2
and much more simple, just use methods to modify arrays (never modify them directly) (check this: https://vuejs.org/2016/02/06/common-gotchas/#Why-isn%E2%80%99t-the-DOM-updating even old and DOM related, is still valid)
So just find your object and replace with splice in your mutation:
const index = state.objectsArray.map(o => o.id).indexOf(newObject.id);
state.objectsArray.splice(index, 1, newObject);
Solution 3
ES6
way of updating
//mutations UPDATE:
[mutationType.UPDATE_CATEGORY] (state, payload) {
state.categories = [
...state.categories.map(item =>
item.id !== updatedItem.id ? item : {...item, ...updatedItem}
)
]
}
//mutations CREATE:
[mutationType.CREATE_CATEGORY] (state, category) {
state.categories = [category, ...state.categories] //Append to start of array
}
//mutations DELETE:
[mutationType.DELETE_CATEGORY] (state, id) {
state.categories = [
...state.categories.filter((item) => item.id !== id)
];
}
Comments
-
Thuan Nguyen almost 2 years
As Vuex, I'm trying to update an object using form. My code like this.
In store:
const state = { categories: [] }; //mutations: [mutationType.UPDATE_CATEGORY] (state, id, category) { const record = state.categories.find(element => element.id === id); state.categories[record] = category; } //actions: updateCategory({commit}, id, category) { categoriesApi.updateCategory(id, category).then((response) => { commit(mutationType.UPDATE_CATEGORY, id, response); router.push({name: 'categories'}); }) }
Template in .Vue file:
<form> <div class="form-group"> <label for="Name">Name</label> <input type="text" class="form-control form-control-sm" name="name" v-model.lazy="category.name" required> </div> <div class="form-group"> <label for="Slug">Slug</label> <input type="text" class="form-control form-control-sm" name="slug" v-model.lazy="category.slug" required> </div> <div class="form-group"> <label for="Avatar">Avatar</label> <input type="text" class="form-control form-control-sm" name="avatar" v-model.lazy="category.avatar" required> </div> <div class="form-group"> <label for="Description">Description</label> <textarea type="text" class="form-control form-control-sm" rows="5" name="description" v-model.lazy="category.description"></textarea> </div> <div class="form-group"> <button type="submit" @click.prevent="updateCategory" class="btn btn-outline btn-sm">Update</button> </div> </form>
And in script:
export default { data() { return { category: {} } }, methods: { getCategoryById(id) { axios.get(`categories/${id}`) .then(response => { this.category = response.data; }) .catch(error => { console.log(error); }) }, // Using mutation. updateCategory() { this.$store.dispatch('updateCategory', this.$route.params.id, this.category); console.log(this.category); //Display exactly data changed. } }, created() { this.getCategoryById(this.$route.params.id); } }
My problem is when I click Update. It nothing change. I did print
category
Object in console. It displays exactly what I expected. But after click Update button. It hasn't changed.Anyone can tell me why and give me solution?? Thanks.
-
Bizmarck over 3 yearsWhy are you creating a new array instead of calling
splice
? -
ittus over 3 years
splice
doesn't change the object reference, so it doesn't trigger Vue reactivity