Skip to content

Instantly share code, notes, and snippets.

@mib200
Created March 19, 2018 08:35
Show Gist options
  • Save mib200/296306fdbd74b4f102086cf6a336c712 to your computer and use it in GitHub Desktop.
Save mib200/296306fdbd74b4f102086cf6a336c712 to your computer and use it in GitHub Desktop.
A vue mixin to automatically set loading state
<template>
<div id="app">
<button :disabled="loading" @click="triggerAction">Trigger action</button>
<div v-if="loading">Loading....</div>
<div v-else>Not loading</div>
</div>
</template>
<script>
export default {
data() {
return {
users: [],
loading: false
};
},
methods: {
triggerAction() {
this.loadData();
},
loadData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 1500);
});
}
},
loading: {
methods: ["loadData"],
property: "loading"
}
};
</script>
import Vue from "vue";
import App from "./App.vue";
import loadingMixing from "./loadingMixin";
Vue.use(loadingMixing);
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
el: "#app",
components: { App },
template: "<App/>"
});
export default {
install(Vue) {
Vue.mixin({
methods: {
/**
* Intercepts a Promise (action) and sets a local property
* to true before executing that promise. After promise is fulfilled or rejected,
* the property is set to false
*
* @param {Promise} action promise to set loading before and after promise was fulfilled/rejects
* @param {string} localProperty instance property name to set loading value
* @param {string} [defaultValue] default property name to set
*/
registerLoading(action, localProperty, defaultValue = false) {
this[localProperty] = defaultValue;
let originalMethod = this[action];
this[action] = function() {
this[localProperty] = true;
return originalMethod
.apply(this, arguments)
.then(data => {
this[localProperty] = false;
return Promise.resolve(data);
})
.catch(err => {
this[localProperty] = false;
});
};
}
},
mounted() {
let { loading } = this.$options;
/**
* We are looking for loading: {} in the component instance
* If we find it, then we search for `methods` and `property` attributes so we can handle them
*/
if (loading) {
let { methods, property, defaultValue } = loading;
if (methods.length) {
methods.forEach(method => {
this.registerLoading(method, property, defaultValue);
});
}
if (typeof methods === "string") {
this.registerLoading(methods, property, defaultValue);
}
}
}
});
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment