2

I have a Vue component with 5 input elements. As a exercise to learn VueX I wanted to manage the user input in a Vuex store. Let's assume each input represents a line in a poem. My state, mutation and actions look like that

state: {
    poem: {
      line1: '',
      line2: '',
      line3: '',
      line4: '',
      line5: '',
    }
  },
  mutations: {
    setPoem(state, line) {
      state.poem = {...state.poem, ...line}
    },
    resetPoem(state) {
      state.poem = {
        line1: '',
        line2: '',
        line3: '',
        line4: '',
        line5: '',
      }
    }
  },
  actions: {
    setPoem({commit}, line) {
      commit('setPoem', line)
    },
    resetPoem({commit}) {
      commit('resetPoem')
    },
  },

Looking the documentation I found that I could use v-model as usual but with a two-way computed property: https://next.vuex.vuejs.org/guide/forms.html#two-way-computed-property

But it seems not very DRY to create a computed property for each input element like to:

computed: {
            line1: {
                get() {
                    return this.$store.state.poem.line1;
                },
                set(value) {
                    this.$store.dispatch('setPoem', {line1: value})
                }
            },
            line2: {
                get() {
                    return this.$store.state.poem.line2;
                },
                set(value) {
                    this.$store.dispatch('setPoem', {line2: value})
                }
            },
            line3: {
                get() {
                    return this.$store.state.poem.line3;
                },
                set(value) {
                    this.$store.dispatch('setPoem', {line3: value})
                }
            },
            line4: {
                get() {
                    return this.$store.state.poem.line4;
                },
                set(value) {
                    this.$store.dispatch('setPoem', {line4: value})
                }
            },
            line5: {
                get() {
                    return this.$store.state.poem.line5;
                },
                set(value) {
                    this.$store.dispatch('setPoem', {line5: value})
                }
            }
        },

My template looks like this:

<form class="form-group" v-on:submit.prevent="addDocument">
            <input v-model="line1" type="text" />
            <p class="error">{{errorMsg1}}</p>
            <input v-model="line2" type="text" />
            <p class="error">{{errorMsg2}}</p>
            <input v-model="line3" type="text" />
            <p class="error">{{errorMsg3}}</p>
            <input v-model="line4" type="text" />
            <p class="error">{{errorMsg4}}</p>
            <input v-model="line5" type="text" />
            <p class="error">{{errorMsg5}}</p>
            <button type="submit">Send Poem</button>
        </form>

How can I refactor this? Is there a best practice to manage state of multiple forms?

1 Answer 1

1

You can use vuex-map-fields

<script>
import { mapFields } from 'vuex-map-fields';

export default {
  computed: {
    ...mapFields([
      'poem.line1',
      'poem.line2',
      'poem.line3',
      // ...
    ]),
  },
};


</script>

and in your store, you can import the getField and updateField to fetch and mutate data

...
getters: {
  getField,
},
mutations: {
  updateField,
}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.