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.
You are setting loading to false before you check for the existence of the handler. Since you bind the button's disabled attribute to loading, you are disabling the button and preventing the native click event from firing.
Just set the loading property after you've checked for the handler:
if (typeof this.handler !== 'undefined') {
this.loading = true;
...
}
Here's a fiddle.
For the record, here's what I ended up doing:
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))
} else {
this.$el.form.submit()
}
}
This allows me disable the form on click and show the loading status, but still force submission.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With