Skip to content

Instantly share code, notes, and snippets.

@dohomi
Last active August 30, 2017 08:15
Show Gist options
  • Save dohomi/a9320906291f9920b164bc41d363c0b6 to your computer and use it in GitHub Desktop.
Save dohomi/a9320906291f9920b164bc41d363c0b6 to your computer and use it in GitHub Desktop.
<template>
<v-form ref="form" v-model="valid">
<slot></slot>
</v-form>
</template>
<script>
export default {
props: {
customElements: {
type: Array,
default: () => ['html-field'] // add all custom form elements
}
},
data () {
return {
valid: false,
modified: {},
initial: {}
}
},
watch: {
'$store.state.triggerSave' () {
this.submitForm()
},
modified (v) {
this.$emit('onFormDirty', !!Object.keys(v).length)
},
valid (v) {
this.$emit('input', v)
}
},
computed: {
allInputs () {
const allVuetifyInput = this.$refs.form.getInputs()
// add non-vuetify elements here:
const htmlElement = this.$refs.form.$children.filter(child => this.customElements.includes(child.$options._componentTag))
return allVuetifyInput.concat(htmlElement)
}
},
mounted () {
// IMPORTANT: set name or fieldName attribute on all form input fields
this.$vuetify.load(() => {
this.allInputs.forEach((child) => {
const name = (child.$attrs && child.$attrs.name) || child.fieldName
this.appendRules(child)
const watcher = child.$props.hasOwnProperty('inputValue') ? 'inputValue' : 'value'
child.$watch(watcher, (v, oldV) => {
this.changeDetection(name, v, oldV)
})
})
})
},
methods: {
/**
*
* public function to reset all form input fields
*/
resetForm () {
this.modified = {}
this.initial = {}
},
/**
* appends all rules to the form input elements
*
* @param element
*
*/
appendRules (element) {
const props = element.$props
const oldRules = props.rules
const rules = []
const onRequiredRule = (v) => !!v || 'Required field'
const onEmailRule = (v) => !v || /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(v) || 'Email must be valid'
if (props.required) {
rules.push(onRequiredRule)
}
if (props.type === 'email') {
rules.push(onEmailRule)
}
if (rules.length && oldRules.constructor === Array) {
for (const rule of rules) {
element.$props.rules.push(rule)
}
}
},
/**
*
* @param name
* @param changedValue
* @param oldValue
*/
changeDetection (name, changedValue, oldValue) {
if (!this.initial.hasOwnProperty(name)) {
if (oldValue === undefined) {
if (changedValue.constructor === Boolean) {
oldValue = false
} else if (changedValue.constructor === String) {
oldValue = ''
} else if (changedValue.constructor === Array) {
oldValue = []
}
}
this.$set(this.initial, name, oldValue)
this.$set(this.modified, name, changedValue)
} else {
this.$set(this.modified, name, changedValue)
if (this.modified[name] === this.initial[name]) {
this.$delete(this.modified, name)
}
}
},
/**
* emit form if valid
*/
submitForm () {
const form = this.$refs.form
const valid = form.validate()
if (valid) {
// don't forget to call resetForm after mutation on component side like => this.$refs.form.resetForm()
this.$emit('onSubmit', this.modified)
}
}
}
}
</script>
<form-container @onSubmit="onSubmit" @onFormDirty="$store.dispatch('setCanSave',$event)" ref="form">
<!-- ADD any vuetify form components here -->
</form>
<script>
export default {
methods:{
onSubmit(){
// => here is your mutation call
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment