How to make a form handling with vuex

ยท

2 min read

ps: Republished from dev.to

#Problem

Let's say you want to save the input of your form on the state of vuex.

Maybe someone new to vuex would try something like this:

<input id="name" name="name" type="text" v-model="$store.state.user.name">

If you try this you will see that:

  1. It doesn't work
  2. Even if it worked, it is totally against the purpose of vuex, that is never have a change of state without it being made by a mutation.

Always send a mutation to change something.

Now, with that in mind, if you look into the documentation of vuex you will find the following:

[...] An alternative approach is using a two-way computed property with a setter:

<input v-model="message">
// ...
computed: {
  message: {
    get () {
      return this.$store.state.obj.message
    },
    set (value) {
      this.$store.commit('updateMessage', value)
    }
  }
}

click here to see.

You can use the v-model to change, but you will need to register a computed property with a getter and a setter to change the state.

Works? Works.

But let's say you have a form, you will need to make a getter and a setter to every input. This works, but isn't practical.

The best way to do it, in my opinion, is to use the principles of clean code to make it:

export function mapFields(options) {
  const object = {};
  for (let x = 0; x < options.fields.length; x++) {
    const field = [options.fields[x]];
    object[field] = {
      get() {
        return this.$store.state[options.base][field];
      },
      set(value) {
        this.$store.commit(options.mutation, { [field]: value });
      }
    };
  }
  return object;
}

Where mapField is the function that map all the field and handle the form. Options is an object with a field which is the field you want to map and a base to refer.

At the end it will only return the getter and setter to us, not so different from before, but with a lot less code.

EDIT: I forgot to show how to use it, so here it is.

I would put it on some helper.js, so i can just import it from my userForm.vue, like this:

<script>
import { mapFields } from "@/helpers.js"

export default {
  computed: {
    ...mapFields({
    fields: ["name", "email", "street", "zipcode"],
    base: "user",
    mutation: "UPDATE_USER"
    }),
...

Hope you enjoyed my first post here, any questions comment bellow! ๐Ÿ˜Ž

#Happy new year

Did you find this article valuable?

Support Matheus Gomes - Frontend Engineer by becoming a sponsor. Any amount is appreciated!

ย