Menu
Dev Bay – front-end tips
  • Front-end tips
  • Back-end tips
  • Converters
Dev Bay – front-end tips

VueJS – loading spinner component

Posted on March 11, 2021July 26, 2022

Loaders or spinners are popular way to fill empty container while its content is loading asynchronously. We use it – typically – when some content is loading, by using ajax request or something is processing in the background. We can use loading spinner in VueJS as a separate component in very nice and clean manner by using VueJS functionality – like components, lifecycle hooks and props. With that we can build reusable loading spinner component which will work in the same manner always when we need to do e.g. async request for content

Table of Contents

  • VueJS demo example for spinner usage
  • Create Vue loading spinner component
  • How to use loading spinner VueJS component
    • Related posts:

VueJS demo example for spinner usage

Just for your information – I started in my example VueJS project directly from Vue CLI.

In this article we will create a “Loader-spinner” component in Vue with demo app like in frame below. Click there on “REFRESH DATA” to see loading spinner component.

Click “Refresh data” button to see loading spinner Vue component again.

Create Vue loading spinner component

First thing here is to create a new VueJS component for a spinner. This will be very small component. As we are using Vue CLI, then of course, we use single component files with .vue extension (Single File Component), so there is HTML (template), JavaScript and CSS code inside one file.

<template>
  <div v-if="active" class="loader-wrapper">
    <div class="loader">
      <div></div>
      <div></div>
      <div></div>
      <div></div>
    </div>
    <p>{{ text }}</p>
  </div>
</template>

<script>
export default {
  name: 'Loader',
  props: {
    active: Boolean,
    text: String
  }
}
</script>

<style scoped>
  p {
    font-size: 0.8em;
    font-weight: 300;
    margin-top: 5px;
    letter-spacing: 1px;
    color: rgb(82, 82, 82);
  }

  .loader-wrapper {
    text-align: center;
  }

  .loader {
    display: inline-block;
    position: relative;
    width: 80px;
    height: 80px;
  }
  .loader div {
    box-sizing: border-box;
    display: block;
    position: absolute;
    width: 64px;
    height: 64px;
    margin: 8px;
    border: 8px solid #6916a0;
    border-radius: 50%;
    animation: loader 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
    border-color: #6916a0 transparent transparent transparent;
  }
  .loader div:nth-child(1) {
    animation-delay: -0.45s;
  }
  .loader div:nth-child(2) {
    animation-delay: -0.3s;
  }
  .loader div:nth-child(3) {
    animation-delay: -0.15s;
  }
  @keyframes loader {
    0% {
      transform: rotate(0deg);
    }
    100% {
      transform: rotate(360deg);
    }
  }
</style>

Let’s check code above step by step:

  1. The most important thing here is the v-if="active" statement. The active variable is a props received from parent (hosting) component, which tells loader to show or hide.
    The second prop used here is message – this text also has v-if statement, so it is visible only in message is provided by the parent component.
  2. Spinner component JavaScript code is very simple – it contains only name of component and props definition.
  3. We use here a loading spinner as CSS animation, so the CSS code is more advanced, but more or less – this is a normal CSS animation, you can find it a lot on the internet.

And loader component code in parent component is as following:

<loader :active="loaderActive" message="Please wait 5 seconds" />

Where loaderActive variable is passed as :active prop – so change true/false of loaderActive from parent Vue component, manages visibility of loader.

How to use loading spinner VueJS component

To show you how to use loading component I have created very basic Vue CLI app. Long story short:

This app simulate ajax request to get employees list from the server.

When application is waiting for the server response – the loading spinner is displayed. When employees list is downloaded – the table is visible. There is also a button to refresh employees list download simulation.

What are the most important things in using loader in optimized and clean way? – Let’s go step by step by key features of my vue-loader-spinner demo app:

  1. Move whole loader functionality into VueJS mixins – mixin something like a part of component shared between many components. Read more here in docs.
    export default {
      data: () => {
        return {
          loaderActive: false,
        }
      },
      methods: {
        showLoader () {
          this.loaderActive = true;
        },
        hideLoader () {
          this.loaderActive = false;
        },
      }
    }
  2. In main component of demo VueJS app App.vue we have basic functionality:
    – loading spinner triggered by loaderActive variable (from mixin)
    – container with refresh data button and the table with employees list. It’s visibility is turned when employees data is inside employees array.
  3. In JavaScript code we import first all needed external files and declare Vue component with our mixin import, methods definitions and mounted VueJS lifecycle hook. What is important now and what is the right approach:
    – if the data (employees table) must load just after page is opened, then request must start just when component is built, so mounted hook is the best choice. There we run this.loadData(); method.
  4. We can have also some kind of button which will trigger ajax call on user click (not when page is opened). In our example we have Refresh data button.
  5. Data request loadData() method must have always – on the beginning – activation of Vue loading spinner component – this.showLoader() method from mixin, and after data download success or reject – hiding of loader – this.hideLoader() method from mixin.

Related App.vue code:

<template>
  <div id="app">
    <h1>VueJS loader-spinner</h1>
    <loader :active="loaderActive" message="Please wait 5 seconds" />

    <div v-show="employees.length">
      <button @click="refreshData">Refresh data</button>

      <table>
        <thead>
          <tr>
            <th>index</th>
            <th>age</th>
            <th>eyeColor</th>
            <th>name</th>
            <th>gender</th>
            <th>company</th>
            <th>email</th>
            <th>phone</th>
            <th>salary</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="row in employees" :key="row.index">
            <td>{{row.index}}</td>
            <td>{{row.age}}</td>
            <td>{{row.eyeColor}}</td>
            <td>{{row.name}}</td>
            <td>{{row.gender}}</td>
            <td>{{row.company}}</td>
            <td>{{row.email}}</td>
            <td>{{row.phone}}</td>
            <td><input type="number" v-model="row.salary"></td>
          </tr>
        </tbody>
      </table>
    </div>

  </div>
</template>

<script>
import Loader from './components/Loader.vue'
import { employeesJson } from './mock-data/employees';
import loaderMixin from './mixins/loader';

export default {
  name: 'App',
  components: {
    Loader
  },
  mixins: [loaderMixin],
  data: () => {
    return {
      employees: []
    }
  },
  methods: {
    loadData () {
      this.showLoader();
      setTimeout(() => {
        this.employees = JSON.parse(employeesJson);
        this.hideLoader();
      }, 5000);
    },
    refreshData () {
      this.employees = [];
      this.loadData();
    }
  },
  mounted () {
    this.loadData();
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

table {
  width: 100%;
  max-width: 1200px;
  margin: 20px auto;
}

button {
    padding: 10px;
    background: #07ab85;
    color: #fff;
    font-weight: bold;
    border: none;
    text-transform: uppercase;
    border-radius: 5px;
}

</style>

You can check and download whole code of VueJS loading spinner component with the demo app in our GITLAB HERE.

Related posts:

Insert JavaScript vuejs/react/angular apps into SalesForce page FIREBASE: integrate ADMIN SDK with NodeJS back-end API Create modal window in vanilla JavaScript
©2023 Dev Bay – front-end tips | Powered by SuperbThemes & WordPress