Search code examples
javascriptarraysvue.jsvuex

How to add new values to an array object using Vuex?


I'm new with vuex, and I'm trying to store objects into an array called orders that have place on the store.js file.

I try to store the values from an object (e.g me.title) into an array that is in the store file by clicking on the button that triggers the method(triggerFunction), but I encountered two problems:

1 - On the console log, I observe that the only variable that is updated is state.order.title, the others remain as undefined (e.g orders.calories)

2 - Also, the state.orders array is empty and no value is pushed into state.orders, as programmed in the mutation.

app.vue

<template>
<p class="genric-btn primary circle text-uppercase" v-on:click="triggerFunction(me.title,me.description,me.price,me.calories)">add to cart</p>
</template>

<script>
export default {
    data () {
        return {
            me:{
                title:"Hamburger",
                description:"Something here",
                price:"25",
                calories:"10"
            },
        }
  },
methods:{
   triggerFunction: function(title,description,price,calories){  
      this.$store.dispatch('triggerFunction',title,description,price,calories)
    },
}
</script>

store.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);

export const store = new Vuex.Store({
    state:{
        order:{title:'',description:'',price:0,calories:0,qty:0},
        orders:[],
    },
    mutations:{
        triggerFunction: (state,title,description,price,calories) => {
            state.order.title = title,
            state.order.description = description,
            state.order.price = price,
            state.order.calories = calories
            state.order.qty = 1
            state.orders.push(state.order)
                        console.log(state.order)
                        console.log(state.orders)
        },
    },
    actions:{
        triggerFunction: (context,title,description,price,calories) => {
            context.commit('triggerFunction',title,description,price,calories)
        }
    },
})

Solution

    1. Mutations and actions have 2 default parameters. First is the store's state, the second is the payload.

    2. The store won't observe object key changes, in this case use Vue.set. But it's okay, if your store's order variable is not reactive.

    3. You can use the data variables in the component, you don't have to pass it as a parameter. In case you are not using v-for.

    Here is the correct call of the action:

    <template>
        <p class="genric-btn primary circle text-uppercase" v-on:click="triggerFunction(me.title,me.description,me.price,me.calories)">add to cart</p>
    </template>
    
    <script>
    export default {
        data () {
            return {
                 me:{
                    title:"Hamburger",
                    description:"Something here",
                    price:"25",
                    calories:"10"
                },
            }
      },
      methods:{
          triggerFunction: function(title,description,price,calories){  
          this.$store.dispatch('triggerFunction', {
              title: title,
              description: description, 
              price: price, 
              calories: calories
          }) // or ES6 if the value name equals with the key {title,description, price, calories}
        },
    }
    </script>
    

    Here is the correct store:

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex);
    
    export const store = new Vuex.Store({
        state:{
            order:{title:'',description:'',price:0,calories:0,qty:0},
            orders:[],
        },
        mutations:{
            triggerFunction: (state, payload) => {
                Vue.set(state.order, 'title', payload.title);
                Vue.set(state.order, 'description', payload.description);
                Vue.set(state.order, 'price', payload.price);
                Vue.set(state.order, 'calories', payload.calories);
                Vue.set(state.order, 'qty', 1);
                state.orders.push(state.order);
            },
        },
        actions:{
            triggerFunction: (context, payload) => {
                context.commit('triggerFunction', payload)
            }
        },
    })