84 lines
2.3 KiB
Vue
84 lines
2.3 KiB
Vue
<template>
|
|
<component :is="tag" @click.capture.stop="call" type="button" :class="buttonClass">
|
|
<span v-if="promise && runIcon">
|
|
<i :class="runIcon"></i>
|
|
</span>
|
|
<span v-else-if="icon" class="icon is-small">
|
|
<i :class="icon"></i>
|
|
</span>
|
|
<span v-if="$slots.default"><slot name="default"/></span>
|
|
</component>
|
|
</template>
|
|
<script>
|
|
import Model from '../model'
|
|
|
|
/**
|
|
* Button that can be used to call API requests on provided url
|
|
*/
|
|
export default {
|
|
emit: ['start', 'done'],
|
|
|
|
props: {
|
|
//! Component tag, by default, `button`
|
|
tag: { type: String, default: 'a'},
|
|
//! Button icon
|
|
icon: String,
|
|
//! Data or model instance to send
|
|
data: Object,
|
|
//! Action method, by default, `POST`
|
|
method: { type: String, default: 'POST'},
|
|
//! If provided open confirmation box before proceeding
|
|
confirm: { type: String, default: ''},
|
|
//! Action url
|
|
url: String,
|
|
//! Extra request options
|
|
fetchOptions: {type: Object, default: () => {return {}}},
|
|
//! Component class while action is running
|
|
runClass: String,
|
|
//! Icon class while action is running
|
|
runIcon: String,
|
|
},
|
|
|
|
computed: {
|
|
//! Input data as model instance
|
|
item() {
|
|
return this.data instanceof Model ? this.data
|
|
: new Model(this.data)
|
|
},
|
|
|
|
//! Computed button class
|
|
buttonClass() {
|
|
return this.promise ? this.runClass : ''
|
|
}
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
promise: false
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
call() {
|
|
if(this.promise || !this.url)
|
|
return
|
|
if(this.confirm && !confirm(this.confirm))
|
|
return
|
|
|
|
const options = Model.getOptions({
|
|
...this.fetchOptions,
|
|
method: this.method,
|
|
body: JSON.stringify(this.item.data),
|
|
})
|
|
this.promise = fetch(this.url, options).then(data => {
|
|
const response = data.json();
|
|
this.promise = null;
|
|
this.$emit('done', response)
|
|
return response
|
|
}, data => { this.promise = null; return data })
|
|
return this.promise
|
|
},
|
|
},
|
|
}
|
|
</script>
|