Update data using vuex

13,640

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)
    ];
}
Share:
13,640
Thuan Nguyen
Author by

Thuan Nguyen

I'm noob :D

Updated on June 20, 2022

Comments

  • Thuan Nguyen
    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
    Bizmarck over 3 years
    Why are you creating a new array instead of calling splice?
  • ittus
    ittus over 3 years
    splice doesn't change the object reference, so it doesn't trigger Vue reactivity