DEV Community

Matheus Gomes πŸ‘¨β€πŸ’»
Matheus Gomes πŸ‘¨β€πŸ’»

Posted on

21 10

How to make a form handling with vuex

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">
Enter fullscreen mode Exit fullscreen mode

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">
Enter fullscreen mode Exit fullscreen mode
// ...
computed: {
  message: {
    get () {
      return this.$store.state.obj.message
    },
    set (value) {
      this.$store.commit('updateMessage', value)
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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"
    }),
...
Enter fullscreen mode Exit fullscreen mode

Hope you enjoyed my first post here, any questions comment bellow! 😎

Happy new year

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (13)

Collapse
 
vamsigandra profile image
Vamsi β€’

Thanks! This is exactly what I am looking for.
Where do you call the mapFields function. Could you please show an example?

Collapse
 
lilarmstrong profile image
Armstrong β€’

I think if you do something like

...

Then, in your methods you define the 'handleSubmi function as follows:

methods:{
handleSubmit(e){
e.preventDefault();
mapFields(e)
//...
}

I think something like the above would do... what do you think?

Collapse
 
matheusgomes062 profile image
Matheus Gomes πŸ‘¨β€πŸ’» β€’

I would use it in the computed property, so i could change the state as i input .

Collapse
 
matheusgomes062 profile image
Matheus Gomes πŸ‘¨β€πŸ’» β€’

My fault, I will edit the post to answer you, sorry for this and thanks for asking.

Collapse
 
mordechairoth profile image
mordechairoth β€’

Thank you! for this amazing super cool solution. I was searching the web for a normal not redundant way to deal with forms when using Vuex and thank god I bumped into this post. This is an amazing and easy solution, thanks.

p.s. there's a syntax error in the example 'const fields = [options.fields[x]]', the outer square brackets should be removed.

Collapse
 
wakeupmh profile image
Marcos Henrique β€’

Awesome post, congrats gomito 🀘

Collapse
 
themsiqueira profile image
Siqueira β€’

Congratulation, it’s a great article!

Collapse
 
matheusgomes062 profile image
Matheus Gomes πŸ‘¨β€πŸ’» β€’

Thanks man!

Collapse
 
lilarmstrong profile image
Armstrong β€’

Lovely... lovely article. Thanks

Collapse
 
unaimian profile image
U.N β€’ β€’ Edited

Thanks for this elegant solution. But what about nested fields in base? It doesn't seem to be working for nested objects

Collapse
 
assoft profile image
Assoft β€’

This is awesome. Thank you.

Collapse
 
dcruz1990 profile image
Dennis Quesada Cruz β€’

WoW! Awesome! i was looking for some like that!!

Collapse
 
sergiosuramin profile image
sergiosuramin β€’

can you show us your store?

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

πŸ‘‹ Kindness is contagious

Please leave a ❀️ or a friendly comment on this post if you found it helpful!

Okay