0
votes

I'm trying to use Vuex and I need to use methods inside a computed property as it is in my real project. I can't figure it out how to call the method and store the data in Vuex.

This is a simple example to show what I need to achieve:

my store:

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

Vue.use(Vuex);

export const store = new Vuex.Store({
    state: {
          calculations: {
              number: 1,
              letter: 'a',

              combinationA:'test',
          }
    },
    getters:{
    },
    mutations:{
        commit_number(state, val){state.calculations.number = val},
        commit_letter(state, val){state.calculations.letter = val},
        commit_combinationA(state, val){state.calculations.combinationA = val},
    },
    actions: {
    }
})

and this is my component

<template>
<div>
    <div>
        choose a number:
            <input v-model="number" type="number">
    </div>
<br>
<br>
    <select  v-model="letter" > 
        choose a letter
        <option value="a">a</option>
        <option value="b">b</option>
        <option value="c">c</option>
    </select>

<p>combination A: {{ combinationA }}</p>
<p>combination A without Vuex: {{ combination_no_vuex }}</p> 

</div>
</template>

<script>

export default {

    methods: {
        MethodCombinationA(letter, number){
            let result = String(letter).concat(number);
            return result;
        },
    },
    computed: {
        number: {
            get () { return this.$store.state.calculations.number;},
            set (value) { this.$store.commit('commit_number', value); }
        },
        letter: {
            get () { return this.$store.state.calculations.letter;},
            set (value) { this.$store.commit('commit_letter', value ); }
        },

        combinationA: {
           get () { return this.$store.state.calculations.combinationA;},
        // set (value) { this.$store.commit('commit_combinationA', this.MethodCombinationA(this.letter, this.number) ); }
        //
        // not working, this is the idea
        },

        combination_no_vuex() {
            return this.MethodCombinationA(this.letter, this.number);
        }
    }
}
</script>

Of course the computed property 'combination_no_vuex' is working as expected, and I would like to store/commit 'combinationA' as 'combination_no_vuex' and then using it in other components. I know Is pretty basic thing, but I'm stuck at the moment!

--edit-- I'm pretty sure this is not the best idea, but somehow it works:

I added an action:

    actions: {
        commit_combinationA(context, payload) {
            context.commit('commit_combinationA', payload);
          }
        }

then, when I get the computed property, it fires the method, then I dispatch it using a watch.

<template>
<div>
    <div>
        choose a number:
            <input v-model="number" type="number">
    </div>
<br>
<br>
    <select  v-model="letter" > 
        choose a letter
        <option value="a">a</option>
        <option value="b">b</option>
        <option value="c">c</option>
    </select>

<p>combination A: {{ combinationA }}</p>
<p>combination A alias: {{ combinationAalias }}</p>
<p>combination A without Vuex: {{ combination_no_vuex }}</p> 

</div>
</template>

<script>
import { mapGetters, mapActions } from 'vuex';
export default {

    methods: {
        MethodCombinationA(letter, number){
            const result = String(letter).concat(number);
            return result;
        },
    },
    computed: {
        number: {
            get () { return this.$store.state.calculations.number;},
            set (value) { this.$store.commit('commit_number', value); }
        },
        letter: {
            get () { return this.$store.state.calculations.letter;},
            set (value) { this.$store.commit('commit_letter', value ); }
        },
        combinationA: {
            get () { return this.MethodCombinationA(this.letter, this.number)},
        },
        combinationAalias(){
            return this.$store.state.calculations.combinationA;
        },
        combination_no_vuex() {
            return this.MethodCombinationA(this.letter, this.number);
        }
    },
    watch: {
        combinationA(value){
            this.$store.dispatch('commit_combinationA', value );
        }
    },
}
</script>
2
You need to call an action from your component. Create actions that execute the commit, then run a this.$store.dispatch('action_name', props) from your component.Sander
isn't necessary use actions for synchronous flow.Christian Carrillo

2 Answers

1
votes
methods: {

  MethodCombinationA(letter, number){
    return String(letter).concat(number);
  },

},


computed: {

  number: {
    get() { return this.$store.state.calculations.number; },
    set(value) { this.$store.commit('commit_number', value); },
  },

  letter: {
    get() { return this.$store.state.calculations.letter; },
    set(value) { this.$store.commit('commit_letter', value); },
  },

  combinationA() {
    return this.$store.state.calculations.combinationA;
  },

},


watch: {

  number(value) {
    this.$store.commit('commit_combinationA', this.MethodCombinationA(this.letter, value));
  },

  letter(value) {
    this.$store.commit('commit_combinationA', this.MethodCombinationA(letter, this.value));
  },

},
0
votes

I answering to myself, I find out is better put the logic into the store.

Basically the computed property return a method value. Usign the parameters the method is, of course, riusable.

 <div id="app">
  <div>
    choose a number:
    <input v-model="number" type="number">
  </div>

  <br>

   <select v-model="letter" > 
     choose a letter
     <option value="a">a</option>
     <option value="b">b</option>
     <option value="c">c</option>
   </select>

  <p>combination A: {{ combinationA }}</p>

</div>

and js:

const store = new Vuex.Store({
  state: {
    number: 1,
    letter: "a"
  },
  mutations: {
    commit_number(state, val) {
      state.number = val;
    },
    commit_letter(state, val) {
      state.letter = val;
    }
  },
  getters: {
    combinationA(state) {
      return (obj1, obj2) => {
        return String(obj1).concat(obj2);
      }
    }
  }
});

new Vue({
  el: "#app",
  store,
  computed: {
    number: {
      get() { return this.$store.state.number; },
      set(value) { this.$store.commit("commit_number", value); }
    },
    letter: {
      get() { return this.$store.state.letter; },
      set(value) { this.$store.commit("commit_letter", value); }
    },
    combinationA(){ return this.$store.getters.combinationA(this.number, this.letter); }
  }
});