Vue.js, Nuxt.js, Vuetify - open progressbar from TypeScript by using store while the process
Tags: vue, nuxt, vuetify, store
Published: 2022-06-13 06:27:48

---
title: Vue.js, Nuxt.js, Vuetify - open progressbar from TypeScript by using store while the process
published: true
description: how to implement the progressbar only while the specific process
tags: Vue, Nuxt, Vuetify, store
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lv03zmelqjayqrnvxs3g.png
---

## 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
```

## Steps to open the progress bar from TypeScript
1. the heavy process is executed.
1. the store of `progressbar` is called.
1. while the heavy process is executed, progress bar component is shown thanks to the store of of `progressbar`.
1. after the heavy process is done, progress bar component is not shown anymore.

## Create a store to control progress bar
Create `store/progressbar.ts`.
```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);
      }
    },
  },
);
```

Register the store by creating `store/index.ts`.
```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,
  },
});
```

Extend the types for `vue` so that the store can be accessed from the file of `vue` extension.
create `types/index.d.ts`
```ts
import { accessorType } from '~~/store';

declare module 'vue/types/vue' {
  interface Vue {
    $accessor: typeof accessorType;
  }
}
```

## 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.
```vue
<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>
```

## 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.
```vue
<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>
```

## References
* [How to create a global snackbar using Nuxt, Vuetify and Vuex.](https://dev.to/stephann/how-to-create-a-global-snackbar-using-nuxt-vuetify-and-vuex-1bda)