I have a component in Vue which I use a substitute for submit buttons. I can pass a handler to it, which the component calls after disabling itself and settings it status as loaded, and it can recover (enable itself again) after errors and display a nifty success animation if all goes well. This works well, with the code below:
// Submit.vue
<template>
<button :type="type" :class="classes" :disabled="loading" @click="onClick">
<span class="flag" v-if="flag"></span>
<slot></slot>
</button>
</template>
<script>
import _ from 'lodash'
export default {
name: 'submit',
props: {
brand: {
type: String,
default: 'primary'
},
// If no handler is provided, will fallback to normal submit button
handler: {
type: Function,
required: false
},
flag: {
type: Boolean,
default: false
}
},
data () {
return {
loading: false,
success: false
}
},
computed: {
type () {
return typeof this.handler !== 'undefined' ? 'button' : 'submit'
},
classes () {
return [
`btn btn-${this.brand}`,
this.loading && !this.success ? 'loading' : null,
this.success ? 'success' : null
]
}
},
methods: {
onClick (event) {
if (this.success) {
event.preventDefault()
return
}
this.loading = true
if (typeof this.handler !== 'undefined') {
// Handler must return a Promise
this.handler.call()
.then(_.bind(() => {
this.onSuccess()
}, this))
.catch(() => {})
.then(_.bind(() => {
this.loading = false
}, this))
}
},
resetSuccess () {
this.success = false
},
onSuccess () {
this.success = true
setTimeout(this.resetSuccess, 2000)
}
}
}
</script>
It falls back to a normal submit button if no handler is passed, assuming all you want is to auto-disable the button when the form is submitted. The only problem is the form is not submitted when I click the button created from the component.
I think it would be fairly easy to force the submission via JS with the onClick method, but I wanted to understand why it doesn't. Is it a browser issue? A security issue? A Vue issue? Or something else I'm missing that might be right in front of me?
Here's a JSFiddle for quick testing: https://jsfiddle.net/03fgwgy5/ The code is not exactly the same, as I'm using single-file components, but the gist is the same and the behaviour can be observed easily.