Multiple Process Loader Management for Vue and Vuex

vuex-loading

Multiple Process Loader Management for Vue and Vuex.

vuex-loading helps to manage multiple loading states on the page without any conflict. It's based on a very simple idea that manages a Vuex store with multiple loading states. The built-in loader component listens its registered loader and immediately become loading state.

Installation

$ npm install vuex-loading
# or if you using Yarn
$ yarn add vuex-loading

Usage

import { createVuexLoader } from 'vuex-loading'

const VuexLoading = createVuexLoader({
  // The Vuex module name, 'loading' by default.
  moduleName: 'loading',
  // The Vue component name, 'v-loading' by default.
  componentName: 'v-loading',
  // Vue component class name, 'v-loading' by default.
  className: 'v-loading',
});

Vue.use(Vuex)
Vue.use(VuexLoading)

const store = new Vuex.Store({
  plugins: [VuexLoading.Store],
});

Then you should register loading module:

new Vue({
  el: '#app',
  store,
  computed: {
    ...mapGetters('loading', [
      /*
        `isLoading` returns a function with a parameter of loader name.
        e.g. `isLoading('creating user')` will return you a boolean value.
      */
      'isLoading',
      /*
        `anyLoading` returns a boolean value if any loader name exists on store.
      */
      'anyLoading',
    ])
  },
  methods: {
    startLoading() {
      /*
        VuexLoading registers $startLoading method with loader name.
        When you start a loader, it pushes the loader name to loading state.
      */
      this.$startLoading('fetching data');
    },
    endLoading() {
      /*
        VuexLoading registers $startLoading method with loader name.
        When you stop a loader, it pulls the loader name from loading state.
      */
      this.$endLoading('fetching data');
    },
  },
});

Global Template Helpers

vuex-loading provides some helpers to you to use in your templates.

$anyLoading

Returns boolean value if any loader exists in page.

<template>
  <progress-bar v-if="$anyLoading">Please wait...</progress-bar>
</template>

$isLoading(loader String)

Returns boolean value if given loader exists in page.

<template>
  <progress-bar v-if="$isLoading('creating user')">Creating User...</progress-bar>
</template>

$startLoading(loader String)

Starts the given loader.

<template>
  <button @click="$startLoading('creating user')">Create User</button>
</template>

$endLoading(loader String)

Stops the given loader.

<template>
  <button @click="$endLoading('creating user')">Cancel</button>
</template>

Global Action Helpers

vuex-loading provides some helpers to you to use in your Vuex stores.

import { createActionHelpers } from 'vuex-loading'
const { startLoading, endLoading } = createActionHelpers({
  moduleName: 'loader'
});

startLoading(dispatcher, loader String [,async callback])

You can trigger loader from the action. This will make your templates cleaner and you will have an accurate loader status.
startLoading will trigger a loading and will end loader after the optional async callback is finished.

Example using the Promise returning callback function

export default {
  actions: {
    async createUser({ commit, dispatch }) {
      const response = await startLoading(dispatch, 'creating user', () => {
        return fetch("...") // Some async job that returns Promise instance.
      });
      commit(types.CREATE_USER, response)
    }
  },
  // ...
}

Example call without a provided callback

export default {
  actions: {
    createUser({ commit, dispatch }) {
      startLoading(dispatch, 'creating user');
      request('/create-user', (response) => {
        endLoading(dispatch, 'creating user')
        commit(types.CREATE_USER, response);
      });
    }
  },
  // ...
}

endLoading(dispatcher, loader String)

Ends given loading from actions.

export default {
  actions: {
    async createUser({ commit, dispatch }) {
      try {
        const response = await startLoading(dispatch, 'creating user', () => { /* ... */ });
        commit(types.CREATE_USER, response)
      } catch (e) {
        // In any unexpected thing occurs on runtime, end the loading.
        endLoading(dispatch, 'creating user')
      }
    }
  },
  // ...
}

Using v-loading Component

In template, you should wrap your content with v-loading component to show loading on it.

<v-loading loader='fetching data'>
  <template slot='spinner'>
    This will be shown when "fetching data" loader starts.
  </template>

  This will be shown when "fetching data" loader ends.
</v-loading>

Better example for a button with loading state:

<button :disabled='$isLoading("creating user")'>
  <v-loading loader='creating user'>
    <template slot='spinner'>Creating User...</template>
    Create User
  </v-loading>
</button>

GitHub