Adding a loading spinner during a search in Vue.js 2

Here is a piece of code from my component:

<template>
    ...
        <input type="text" class="form-control" v-model="rawFilter" placeholder="Search" @keyup="getPlayers">
    ...
</template>

<script>
    import _ from 'lodash'
    ...
    export default {
        ...
        data() {
            return{
                msg:'hello vue',
                rawFilter:'',
                loading:false
            }
        },
        ...
        methods: {
            getPlayers: _.debounce(function(e) {
                const text = e.target.value.trim()
                this.$store.dispatch('getPlayers', {
                  q: text
                })
            },1000),
            ...
        }
    }
</script>

While searching for data, I would like to include a loading icon before displaying the results.

How can I achieve this in vue.js 2?

Answer №1

To enhance user experience, I recommend utilizing a loader with its own vuex state.

  1. Having its own vuex state allows for easy control from any component.
  2. Simple function calls can be used to interact with the loader.
  3. Avoiding the use of props and events comes naturally.

Firstly, identify where the loader will be required:

  1. Will it be used for all API calls?
  2. Is it intended for tasks that are resource-intensive in the browser (e.g., processing a large file)?
  3. Or perhaps it should only appear in specific scenarios (such as when a user attempts to log in).

If the loader is not closely tied to a specific component (as in scenario 1), it would be more logical to include it in your main Vue file (e.g., App.vue if you're using vue-cli).

For example:

<template>
  <div id="app">
    <loader></loader>
    <router-view></router-view>
  </div>
</template>

<script>
import Loader from './components/shared/loader/Loader'

export default {
  name: 'app',
  components: {
    Loader
  }
}
</script>

This approach eliminates the need to include loader.vue in every other component file. Before proceeding, let's examine the loader component and store being utilized.

<template>
  <div class='loader-container' :class='{"show": show, "hidden": !show}'>
    <div class="curved-div">
      <div class="colour-magic">
        <i class='fa fa-circle-o-notch rotate'></i>
      </div>
      <div class="loading">
        {{ loading }}
      </div>
    </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import * as NameSpace from '../../../store/NameSpace'

export default {
  data () {
    return {
      loading: 'Loading...'
    }
  },
  computed: {
    ...mapGetters({
      show: NameSpace.GET_LOADER_STATE
    })
  }
}
</script>

<style scoped>
.loader-container {
  position: fixed;
  width: 100%;
  height: 100%;
  background: rgba(0,0,0,0.8);
}

.curved-div {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translateX(-50%);
  border-radius: .3rem;
  width: 20rem;
  padding:1rem;
  background: white;
  box-shadow: 0 0 .1rem #fefefe;
}

// CSS styling continues...

Please note the utilization of font-awesome for the loader graphic.

Furthermore, here is the relevant store section:</p>

<pre><code>import * as NameSpace from '../NameSpace'

const state = {
  [NameSpace.LOADER_STATE]: false
}

// Store getters, mutations, and actions follow...

A usage example incorporating the store mutation function for managing the loader during an API call:
// This JavaScript file demonstrates how to interact with the store for loader management

login (username, password) {
  loaderSwitch(true)
  return new Promise((resolve, reject) => {
    SomeEndpoint.logIn(username, password, {
      success (user) {
        loaderSwitch(false)
        resolve(user.attributes)
      },
      error (user, error) {
        loaderSwitch(false)
        reject(errorHelper(error.code))
      }
    })
  })
  // Remaining logic...

By adopting this method, the loader component remains independent of individual components where login functionality may be implemented.

Answer №2

To make it work, all you have to do is attach it to a flag and utilize the v-if directive. If you are using vue resource, you can enable the loading flag in the before callback and disable it after receiving the response:

Vue Instance

  methods: {
    loadData() {
      this.$http.get('/search', {
        before: () => {
          this.loading = true;
        }
      }).then(response => {
        // Deal with response
      }).then(() => {
          //set loading flag to false
          this.loading = false;
      })
    }
  },
  data: {
    loading: false
  }

HTML

<div id="app">
  <button @click="loadData">
    Get Data
  </button>

  <!-- Only show if loading is true -->
  <div v-if="loading" v-cloak>
    <i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw"></i>
    <span>Loading...</span>
  </div>
</div>

Check out the JSFiddle link for more details: https://jsfiddle.net/hyeycoan/

Answer №3

To enhance your template, consider including a loading div that can be toggled based on the loading flag. Here is an example:

new Vue({
  el: '#app',
  data: {
    show: true,
isLoading: false,  
  },
methods:{
loadData: function(){
this.isLoading = true;
setTimeout(function(){
this.isLoading = false;
}.bind(this),1000);
}
}
})
.loading{
display: none;
position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    background: rgba(128, 128, 128, 0.5);
}
.loading.show{
display: initial;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
<div id="app">
<div class="loading" v-bind:class="{ show: isLoading }">
<span>Loading</span>
</div>
<button @click="loadData">Load</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
</body>
</html>

To style the loading indicator, you can use CSS to make it look visually appealing. Alternatively, you can explore resources like or for pre-designed options.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Execute async functions sequentially with a queue and limit to only one function running at a time

Within my javascript code, there is an async function named generateThumbnail. This function is triggered by a specific event, such as clicking on a button. The issue I'm facing is that running the function multiple times concurrently leads to a memor ...

The issue with Nuxt 3 page transitions not functioning as expected seems to be

Exploring the possibilities of Nuxt 3, I am eager to implement animated transitions between pages using JavaScript hooks and libraries like gsap or animeJs. In my app.vue file, I have simply placed <NuxtPage/> inside a <Transition> element as ...

The size of the popup does not align properly with the content within it

After creating an extension for Chrome, I specified the dimensions of the popup to be 600 x 300 px. Everything was working perfectly until Chrome updated to version 27. As shown in the screenshot, I set the width and height using CSS, but there is still a ...

Locate and retrieve a document by its unique identifier in MongoDB, and then store its information in an array

I am working with two models: Meal and Ingredient. Let's take a look at their schemas: const mealSchema = new Schema({ title: { type: String, required: true }, image: { type: String, required: false }, ingredients: [{ ingredient: { ...

From what source does the angular framework retrieve its 'data' information?

--- Consider this code snippet from a specific file --- angular.module('storyCtrl', ['storyService']) .controller('StoryController', function(Story, socketio) { var vm = this; Story.getStory() .success(func ...

Unable to dynamically highlight a row in a GridView using JavaScript

Performing this task used to be simple, but it was my first time dynamically generating the GridView. Each cell in the GridView is styled with its own CSS when created. In the RowDataBound event, I set up the highlighting as usual: e.Row.Attributes.Add("o ...

Angular directive specifically meant for the parent element

I am working on a directive that I need to apply to a specific div element without affecting its child elements. The goal is to make the main div draggable, so that when it moves, its child divs move along with it. However, I do not want the child divs to ...

I am attempting to access an Angular variable using JavaScript, but unfortunately, I am encountering some issues

I'm currently implementing the following code: window.onload=function(){ var dom_el2 = document.querySelector('[ng-controller="myCtrl"]'); var ng_el2 = angular.element(dom_el2); var ng_el_scope2 = ng_el2.scope(); console.log ...

"Combining the power of JavaScript countdown with PHP date functionality

I have a JavaScript code that generates countdowns based on the user's PC date. I'm looking for a way to modify the script to use a specific timezone like: <?php date_default_timezone_set('Ireland/Dublin'); $date = date('m/d/Y ...

Select a single radio button containing values that can change dynamically

<input type="radio" on-click="checkDefaultLanguage" id="checkbox" > [[names(name)]] This custom radio input field contains dynamic values and I am attempting to create a functionality where only one radio button can be selected at a time while dese ...

Experiencing the power of DoJo with the latest Wordpress 4

SOLUTION: After some investigation, I discovered that reordering the loading sequence of jQuery UI and DoJo files in the footer resolved the issue. By placing jQuery UI before any DoJo-related files, I ensured jQuery UI was fully loaded before any DoJo scr ...

The issue of duplicated elements arises when Ajax is utilized within Django

Upon form submission, a Graph is generated using Plotly. Utilizing Ajax to submit the form without refreshing the page results in duplicating the form div on the screen. How can this issue be resolved? The code snippet below showcases my implementation wit ...

Creating a new table based on an if statement from an HTML table index value of x

Hey everyone, I could really use your assistance. I've been attempting to create an if statement based on the values in my HTML table's index-x (where x represents the column index). I've successfully managed to convert the table into an arr ...

ReactJS with Redux Form and Material UI framework featuring automatic typing and field clearing capabilities

Currently, I am in the process of developing a nested form framework that utilizes both the redux form and material ui frameworks. The components are already built up to this point - you can view them here: https://codesandbox.io/s/heuristic-hopper-lzekw ...

What are the steps to troubleshoot an unexpected 302 redirect caused by an Ajax request?

I'm attempting to retrieve data from a database using this ajax request: axios.get('/about-info') web.php: Route::get('/about-info', [CMSController::class, 'aboutInfo']); CMSController.php: public function aboutInfo() { ...

Error: The server is unable to process the POST request to /api

Currently following a tutorial on YouTube: https://www.youtube.com/watch?v=4ECVE6TXKLQ&list=PLI-gk4ISRzCPlJjCz3yuAhL8vnmK6KWr7&index=11 After setting up a server listening on port 8080 and connecting to MongoDB Atlas successfully, the next step ...

Sorting through an array of objects based on TypeScript's union types

My array consists of objects such as: array = [{name: 'something'}, {name: 'random'}, {name: 'bob'}] I have created a union type type NamesType = 'something' | 'bob' Can the array be filtered based on t ...

Ensure that the section is fixed at the top when it reaches that point, and unfixed when the

Looking to keep a section fixed at the top of the browser when it reaches that point on scroll down, but also wanting it to unstick when the user scrolls back up and the previous section reappears. Currently detecting the distance from the top to the sect ...

Display an image using a modal window and Ajax XMLHttpRequest

I was tasked with creating a button that can load various types of content (text, images, videos, etc) into a modal popup window using Ajax without any frameworks. So far, I've been successful with text but have run into issues with loading images. De ...

Can you identify a way to determine in which parent window your child was opened?

I am facing an issue where I have a component being utilized as a child component in two different places. I am trying to implement a back button that directs the user to the correct route depending on the parent component. Currently, I can achieve this wi ...