Display a loading indicator while rendering several Vue components

My current challenge involves loading multiple Vuetify card components based on the selected category at the top of the page.

The issue arises when the array renders more than 50 cards, causing a significant delay in loading time. While I am not overly concerned about the duration it takes to load, I do find it frustrating that the page becomes unresponsive during rendering and I am unable to use a loading indicator.

To illustrate the problem, I created a sample scenario here:

https://jsfiddle.net/owa1czqx/2/

<script src="https://unpkg.com/vue"></script>

<div id="app">  
  <button v-for="cat in cats" :key="cat" @click="catSelected(cat)">{{cat}}</button>
  <p v-for="item in items">{{ item }}</p>
</div>

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!',
    cats: ['cat 1', 'cat 2'],
    items: []
  },
  methods: {
    catSelected(newCat) {
      this.items = []
        for (let i = 0; i <= 50000; i++) {
        this.items.push(i + '. ' + newCat)
      }
    }
  }
})

I am looking for a way to provide user feedback indicating that new cards are being loaded before they actually appear. Is there a method to asynchronously render similar to asynchronous data fetching?

Regrettably, pagination or autoscroll loading is not a feasible solution in my case as it would disrupt the predefined layout.

Answer №1

To display progress in your solution, consider making some modifications. Ensure that the loading is not hidden within the loop; instead, execute it immediately after completion. The updated methods can be found in this Fiddle link:

One approach involves invoking loadSet using a timeout function (as $nextTick did not behave similarly).

timedLoadSet(newCat, offset, step) { 
  var vm = this;
  setTimeout(function() { vm.loadSet(newCat, offset, step); }, 1);
},

The other method handles loading operations.

loadSet(newCat, offset, step) {
  for (let i = offset; i < offset + step && i < this.count; i++) {
    this.items.push(i + '. ' + newCat);
  }
  this.loaded = Math.round(this.items.length / this.count * 100);

  if(this.items.length === this.count) {
    this.loading = false;
  } else {
    this.timedLoadSet(newCat, offset + step, step);
  }
},

Lastly, there is a function that initiates the initial load process.

catSelected(newCat) {
  this.loading = true;
  this.loaded = 0;
  this.items = [];
  var step = Math.round(this.count / 100);

  this.timedLoadSet(newCat, 0, step);
}

Answer №2

Discovered a clever workaround that displays a loading message to the user while all components are rendering.

The only drawback is that user interaction is disabled during this process, but at least there is some feedback indicating that something is in progress.

Nevertheless, this solution resolved my issue as the load times are relatively quick at around 0.5-1 second, which shouldn't inconvenience the user if they are aware that content is loading.

<script src="https://unpkg.com/vue"></script>

<div id="app">  
  <button v-for="cat in cats" :key="cat" @click="catSelected(cat)">{{cat}}</button>
  <p v-if="loading">Loading...</p>
  <p v-else v-for="item in items">{{ item }}</p>
</div>

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!',
    cats: ['cat 1', 'cat 2'],
    items: [],
    loading: false
  },
  methods: {
    catSelected(newCat) {
        const self = this
        self.loading = true
      setTimeout(function() {
        self.items = []
        for (let i = 0; i <= 50000; i++) {
          self.items.push(i + '. ' + newCat)
          self.loading = false
        }
      },0)
    }
  }
})

https://jsfiddle.net/0k8eyb4m/22/

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

Error in delete operation due to CORS in Flask API

After successfully developing a rest api in Flask and testing all api endpoints with Postman, I encountered an issue while working on an application in Javascript that consumes the resources of my api. The problem lies in consuming an endpoint that uses t ...

What is the best way to turn off the legends in chart.js?

I'm having trouble customizing a chart using chart.js because I can't seem to disable the legends within the canvas element. However, I still want to style the legends elsewhere on the page using generateLegend(). Can anyone provide assistance wi ...

Using Vue.js along with vuex and axios allows for data retrieval only upon the second load

After creating a Vue.js app with vuex as a central store and using axios for basic API calls, I implemented the following store action: loadConstituencyByAreaCodeAndParliament({commit}, {parliament_id, area_code}) { axios.get('/cc-api/area-code/ ...

Tips for safeguarding the security of my PHP API when accessed through Ajax using OAuth2

I've developed a cross-origin ajax application that utilizes some personal APIs I created. Now, I'm looking to enhance the security measures so only my application has access to the API. After researching, I came across OAuth2 at OAuth2. I foll ...

The binding on an AngularJS page is only retained by the final directive applied

Having a few directives that need to be reused as elements, I've decided to implement scope isolation. Each directive is associated with its own controller, which retrieves data from MongoDB based on the URL. The issue I'm facing is that only th ...

I am encountering a problem with my Vuex getter where it is sending an Array with a length of 0, but when expanded in the console,

Currently, I'm utilizing Vuex to interact with a Django API in order to fetch count data. state: { DailyCycleDate: [] }, getters: { DailyCycleDate : state => { console.log('Getter') console.log('Length of Array: &apo ...

How can you typically verify the type of an object variable in TypeScript?

How can I verify if the obj variable contains all the properties defined in the Person interface? interface Person { name: string; age: number; } const jsonObj = `{ name: "John Doe", age: 30, }`; const obj: Person = JSON.parse(jsonObj); ...

sort the array based on its data type

Recently diving into typescript... I have an array that is a union of typeA[] | typeB[] but I am looking to filter based on the object's type interface TypeA { attribute1: string attribute2: string } interface TypeB { attribute3: string attri ...

What is the best way to transfer a value from a function to a variable in VueJs?

Currently, I am receiving the base64 of an image URL. When passing the getImage function to the savepdf function and attempting to store the callback function's base64_data in a variable, an error is thrown: An error occurs - Cannot set property &a ...

What are alternate ways to utilize router.back() in vue without relying on a button?

I'm currently working on a project using Vue and its packages. I am looking for a way to navigate to the last page without having to use a physical button within the app itself. Instead, I want to be able to navigate using the browser's back butt ...

Is there any method to determine whether a floated element has been pushed down?

Imagine a dynamic menu with floating elements, each set at a width of 150px. As the menu's width decreases, the elements progressively move to the next row. You are contemplating how to detect when an element has been moved down. One approach could b ...

Combine and emphasize several gridview rows into a single highlighted unit

Imagine you have a gridview that looks like this: FAMILY GROUP COLOR =============================================== | | Poodle | Blue ROW1 | DOG | German Shepherd | Red | | Pitbul ...

Duplicate text content from a mirrored textarea and save to clipboard

I came across some code snippets here that are perfect for a tool I'm currently developing. The codes help in copying the value of the previous textarea to the clipboard, but it doesn't work as expected when dealing with cloned textareas. Any sug ...

Incorporating HTML5 audio elements in JavaScript

I am working on a project where I need to create a grid of 16 audio files with separate links for each in HTML, CSS and JavaScript. Each box in the grid should link to a different audio file. My initial thought was to use a table to achieve this, so I cre ...

Trouble with Bootstrap Popover's visibility

My current setup involves a popover that is not initializing properly. The code I am using is shown below: HTML: <div data-toggle="popover" data-placement="bottom" data-content="xyz">...</div> JavaScript: $(function () { $('[data-t ...

Tips for refreshing an html table without affecting the scroll location?

HTML: <div class="html_table"></div> # Within the html body tag. Utilizing Ajax function to retrieve table data. var $html_table= $('.html_table'); function ajaxCallFunction() { $.ajax({ type: 'POST', ...

An appropriate loader may be required to manage this file type issue, which seems to be occurring consistently on all Vuetify components

Currently, I am working on a project that involves a rails backend and a Vue frontend. Both ends are functioning properly, and my next step is to enhance the visual appeal by incorporating Vuetify. After running vue install vuetify, I encountered Runnin ...

Exploring Nested Routes and Queries in Vue JS

As a beginner in Vue, I have been exploring a demo project and struggling with understanding how routes with query parameters function. The documentation suggests using router.push({ path: 'register', query: { plan: 'private' }}) to gen ...

NodeJS: Using SSH2 to Retrieve the Most Recent 1000 Characters from a Stream

Currently, I have set up a Vue App that includes a component for xterm along with an ssh2/shell client managed by a global Vue plugin. I am able to successfully connect to a server through my ssh plugin using the xterm component and display the ssh strea ...

The HTML Canvas seems to be malfunctioning for some unknown reason

As a beginner in programming, I am struggling to understand why the code below is not working. The first three lines of the script are necessary for another part of the webpage, but I don't see how that would affect the rest of the code: <!DOCTY ...