What is sane way in vuejs + vuex form handling? What is sane way in vuejs + vuex form handling? vue.js vue.js

What is sane way in vuejs + vuex form handling?


I made a little tool which makes form handling wit Vuex a lot easier: vuex-map-fields

Example

Store

import Vue from 'vue';import Vuex from 'vuex';// Import the `getField` getter and the `updateField`// mutation function from the `vuex-map-fields` module.import { getField, updateField } from 'vuex-map-fields';Vue.use(Vuex);export default new Vuex.Store({  state: {    fieldA: '',    fieldB: '',  },  getters: {    // Add the `getField` getter to the    // `getters` of your Vuex store instance.    getField,  },  mutations: {    // Add the `updateField` mutation to the    // `mutations` of your Vuex store instance.    updateField,  },});

Component

<template>  <div id="app">    <input v-model="fieldA">    <input v-model="fieldB">  </div></template><script>import { mapFields } from 'vuex-map-fields';export default {  computed: {    // The `mapFields` function takes an array of    // field names and generates corresponding    // computed properties with getter and setter    // functions for accessing the Vuex store.    ...mapFields([      'fieldA',      'fieldB',    ]),  },};</script>

You can read more about vuex-map-fields on my blog: How to Handle Multi-row Forms with Vue, Vuex and vuex-map-fields


I would use deep watchers for this and have all fields in a object, you could use multiple approaches for saving the data, iterating over Object.keys to store each field with it's variable name in the form object, or storing the entire form, whatever you might need.

You could also use v-model.lazy="form.myfield" to indicate that you only want the binding to update once the user has left the field.

Form component

<template>    <div>        <!-- You can optionally use v-model.lazy="form.field1" to only update once user has exited the field or pressed enter -->        <input v-model="form.field1" />        <input v-model.lazy="form.field2" />    </div></template><script>    export default {        props: ['value'],        data: function () {            return {                internalForm: {                    field1: null,                    field2: null                }            }        },        watch: {            internalForm: {                handler: function (newValue) {                // Emit new form object to parent component so we can use v-model there                this.$emit('input', this.form)                // Or save form data                this.handleFormSave(this.form)                },                // Tell vue to do a deep watch of entire form object to watch child items in the object                deep: true            }        }    }</script>

Parent component

<template>    <form-component v-model="forms.form1" />    <submit-button @click="saveAllFormData" /></template><script>    export default {        data: function () {            return {                forms: {                    form1: null // This will be updated when 'input' is emitted                 }            }        },        watch: {            forms: {                handler: function (newValue) {                    if (allFormsValid && readyToSave)                        saveAllFormData(newValue);                },                deep: true            }        }    }</script>


I had headache regarding this probem to.

Vuex doc describes that we need to update store for every field.It's a loot of typing whatfor?

We make one solution that works.It based on cloning store object to local one.

  //We are passing (vuexstore) 'item' object from parent component:  //<common-item v-bind:item="item" ....  props: ['item'],  // create localItem - this is reactive object for vuex form  data: () => {    return {      localItem: null    }  },  // make clone on created event  created: function() {    this.localItem =  this._clone(this.item)  },  // watch vuexstore 'item' for changes  watch: {    item: function(val) {      this.localItem = this._clone(this.item)    }  },  // map mutations and update store on event  methods: {     ...mapMutations([      'editItem'    ]),    updateItemHandler: function() {      this.editItem({ item: this._clone(this.localItem) })    },    _clone: function(o){      return JSON.parse(JSON.stringify(o))    }  },

Inside form use:

 <input v-model="localItem.text" @keyup="updateItemHandler" type="text" class="form-control"></input>

I think this is only lack of vuex. There should be much shorter and built in solution.