Johnhhorton
11/20/2017 - 3:52 AM

Vuejs Vuetify Vuex form example

util.js Contains computed mappers to make errors and form state repeatable across components comment-create-module.js contains the vuex store. It also references resource vuex stores for the api calls comment-create.vue contains the actual component

<template>
    <div>
        <v-card>
            <v-card-text>
                <h3>New Comment</h3>
                <v-text-field name="content" label="Content" v-model="formData.content" type="text"
                              :error-messages="contentErrors" multi-line></v-text-field>
                <v-btn :class="submitColor" @click="submitComment()">{{submitMessage}}</v-btn>
                <v-progress-linear v-if="submitting" v-bind:indeterminate="true"
                                   :disabled="submitting"></v-progress-linear>
            </v-card-text>
        </v-card>
    </div>
</template>
<script type="text/javascript">
  import { mapState, mapGetters, mapActions } from 'vuex'
  import { mapLaravelErrors, mapFormStatus } from '../../utils/utils'

  export default {
    name: 'comment-create',
    data () {
      return {
        formData: {
          content: '',
          view_id: false,
          user_id: false
        }
      }
    },
    created () {
      this.formData.view_id = this.viewId
      this.formData.user_id = this.$store.state.authModule.me.id
    },
    methods: {
      submitComment () {
        this.$store.dispatch('commentCreateModule/changeFormData', this.formData)
        this.$store.dispatch('commentCreateModule/submitForm')
          .then(() => {
            this.formData.content = ''
          })
          .catch(() => {
            console.error('unforseen error')
          })
      }
    },
    computed: {
      ...mapLaravelErrors('commentCreateModule', ['content']),
      ...mapFormStatus('commentCreateModule')
    },
    props: {
      viewId: {
        type: Number,
        required: true
      }
    },
  }
</script>
import debug from 'debug'

const runDebug = debug('commentCreateModule')

export default {
  namespaced: true,
  modules: {},
  state: {
    formData: {
      content: '',
      user_id: null,
      view_id: null,
    },
    errors: {},
    submitMessage: 'Save',
    redirect: false,
    submitMessageDefault: 'Save',
    submitMessageSaving: 'Saving...',
    submitMessageSuccess: 'Saved!',
    submitting: false,
    submitColor: 'primary',
    submitColorDefault: 'primary',
    submitColorSaving: 'disabled',
    submitSuccessColor: 'success',
  },
  mutations: {
    setContent (state, content) {
      state.content = content
    },
    setFormData (state, formData) {
      state.formData = {...formData}
    },
    setErrors (state, error) {
      state.errors = error
    },
    startSubmitStatus (state) {
      state.submitMessage = state.submitMessageSaving
      state.submitting = true
      state.submitColor = state.submitColorSaving
    },
    succeedSubmitStatus(state){
      state.submitMessage = state.submitMessageSuccess
      state.submitting = false
      state.submitColor = state.submitSuccessColor
    },
    failSubmitStatus (state) {
      state.submitMessage = state.submitMessageDefault
      state.submitting = false
      state.submitColor = state.submitColorDefault
    },
    resetSubmitStatus (state) {
      state.submitMessage = state.submitMessageDefault
      state.submitting = false
      state.submitColor = state.submitColorDefault
    }
  },
  //To use root actions and commits, pass { root: true } to 3rd argument of a commit or dispatch
  actions: {
    changeFormData ({dispatch, commit, getters, rootGetters}, formData) {
      console.log('change form data')
      commit('setFormData', formData)
    },
    submitForm ({dispatch, state, commit, getters, rootGetters}) {
      commit('startSubmitStatus')
      commit('setErrors', {})
      return dispatch('commentsModule/store', state.formData, {root: true})
        .then((response) => {
          return dispatch('viewsModule/show', {id: state.formData.view_id}, {root: true})
        })
        .then((response) => {
          commit('succeedSubmitStatus')
          commit('setErrors', {})
          commit('setContent','')
          setTimeout(()=>{
            commit('resetSubmitStatus')
          },1000)
        })
        .catch((error) => {
          commit('failSubmitStatus')
          commit('setErrors', error)
          setTimeout(()=>{
            commit('resetSubmitStatus')
          },1000)
        })
    }
  },
}

export function mapLaravelErrors (moduleStore = null, errors = []) {
  const computed = errors.reduce((accumulator, value) => {
    accumulator[`${value}Errors`] = function () {
      let module = this.$store.state[moduleStore]
      if (module.errors && module.errors.errors && module.errors.errors[value]) {
        return module.errors.errors[value]
      }
      return []
    }

    return accumulator
  }, {})
  computed.errorMessage = function () {
    let module = this.$store.state[moduleStore]
    if (module.errors && module.errors.message) {
      return module.errors.message
    }
    return null
  }

  return computed
}

export function mapFormStatus (moduleStore = null) {
  return {
    submitMessage(){
      const module = this.$store.state[moduleStore]
      if(typeof module.submitMessage !== 'undefined') return module.submitMessage
    },
    submitting(){
      const module = this.$store.state[moduleStore]
      if(typeof module.submitting !== 'undefined') return module.submitting
      return false
    },
    submitColor(){
      const module = this.$store.state[moduleStore]
      if(typeof module.submitColor !== 'undefined') return module.submitColor
      return 'primary'
    }
  }
}