Nuxtstop

For all things nuxt.js

Vue.js, Nuxt.js, Vuetify - open progressbar from TypeScript by using store while the process

Vue.js, Nuxt.js, Vuetify - open progressbar from TypeScript by using store while the process
4 0

About this post

on the web page, the progress bar tends to be global component.
And, it is preferred to be opened from TypeScript (not from Vue template using v-if ) because the bar should be opened only while the process.
In this post, the way of implementation about progress bar opened from TypeScript is introduced.

Target readers

  • the developers who want to implement progressbar by Vue.js or Nuxt.js
  • the developers who have basics about store and Vuetify.js (some basic parts of store and Vuetify will be omitted.)

Versions

content version
nuxt 2.15.8
nuxt-typed-vuex 0.3.0
vue 2.6.14
vuetify 2.6.1

the directory structure

sampleProject
├componens
| └progressbar.vue
├pages
| └index.vue
├store
| ├index.ts
| └progressbar.ts
└types
  └index.d.ts
Enter fullscreen mode Exit fullscreen mode

Steps to open the progress bar from TypeScript

  1. the heavy process is executed.
  2. the store of progressbar is called.
  3. while the heavy process is executed, progress bar component is shown thanks to the store of of progressbar.
  4. after the heavy process is done, progress bar component is not shown anymore.

Create a store to control progress bar

Create store/progressbar.ts.

import { mutationTree, actionTree } from 'typed-vuex';

// isShown is to control whether progress bar is shown or not
export const state = () => ({
  isShown: false as boolean,
});
export type RootState = ReturnType<typeof state>;

export const mutations = mutationTree(state, {
  change(state, isShown: boolean) {
    state.isShown = isShown;
  },
});

export const actions = actionTree(
  { state, mutations },
  {
    async open({ commit }, action: Function) {
      // only while action is executed, the progress bar is opened
      commit('change', true);
      try {
        await action();
      } finally {
        // even if the argument action throws an error, the progress bar should be closed
        commit('change', false);
      }
    },
  },
);
Enter fullscreen mode Exit fullscreen mode

Register the store by creating store/index.ts.

import {
  getAccessorType,
  getterTree,
  mutationTree,
  actionTree,
} from 'typed-vuex';
// if there is other stores, import here
import * as progressbar from './progressbar';

export const state = () => ({});
export const getters = getterTree(state, {});
export const mutations = mutationTree(state, {});
export const actions = actionTree({ state, getters, mutations }, {});
export const accessorType = getAccessorType({
  state,
  getters,
  mutations,
  actions,
  modules: {
    // if there is other stores, add here
    progressbar,
  },
});
Enter fullscreen mode Exit fullscreen mode

Extend the types for vue so that the store can be accessed from the file of vue extension.
create types/index.d.ts

import { accessorType } from '~~/store';

declare module 'vue/types/vue' {
  interface Vue {
    $accessor: typeof accessorType;
  }
}
Enter fullscreen mode Exit fullscreen mode

Create a progress bar component

By the implementation of this.$store.subscribe, catch the change notification of store progressbar and change the visibility according to isShown store value.

<template>
  <!-- set z-index so that this progress bar can be shown above the modal dialog -->
  <v-overlay z-index="100" :value="isShown">
    <v-progress-circular indeterminate color="primary"></v-progress-circular>
  </v-overlay>
</template>

<script lang="ts">
import Vue from 'vue';

export default Vue.extend({
  name: 'AppProgressbar',
  data() {
    return {
      isShown: false,
    };
  },
  created() {
    this.$store.subscribe((mutation, state) => {
      if (mutation.type === 'progressbar/change') {
        this.isShown = state.progressbar.isShown;
      }
    });
  },
});
</script>
Enter fullscreen mode Exit fullscreen mode

Open progress bar from TypeScript

Create pages/index.vue .
Only in the scope of await this.$accessor.progressbar.open(async () => {}); , the progress bar is shown.

<template>
  <button @click="doHeavyProcess">Execute</button>
</template>

<script lang="ts">
import Vue from 'vue';

export default Vue.extend({
  methods: {
    async doHeavyProcess() {
      await this.$accessor.progressbar.open(async () => {
        // in this scope, the progress bar is shown
        await this.$axios.get('https://example.com');
      });
      // out of the scope of progress bar, the progress bar is not shown
    },
  },
});
</script>
Enter fullscreen mode Exit fullscreen mode

References