Delaying the intensive rendering process in Vue.js and Vuetify: A comprehensive guide

Recently, while working on a project with Vue.js 2 and Vuetify 2.6, I encountered an issue with heavy form rendering within expansion panels. There seems to be a slight delay in opening the panel section upon clicking the header, which is most likely due to the initial rendering process. Although the delay doesn't disrupt functionality, I would like to incorporate a progress indicator that displays instantly while the rendering takes place. Strangely, the progress indicator only shows up once the rendering is complete, even though the UI remains responsive during this time.

Is there a method to postpone the rendering of the panel section so that the progress indicator can first be displayed? Interestingly, the interface isn't unresponsive while the rendering occurs, allowing for the smooth animation of the progress indicator.

Unfortunately, utilizing the "eager" option for expansion panels is not feasible as it significantly slows down the loading time when dealing with numerous panels.

The provided code snippet presents this issue through a demonstrative example.

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data: () => ({
    loading: false
  }),
  methods: {
    click() {
      console.log('click')
      this.loading = true
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a3d5d6c6e3918ddb">[email protected]</a>/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bdcbc8d8c9d4dbc4fd8f938b938c">[email protected]</a>/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a9dfdcccddc0cfd0e99b879d879d">[email protected]</a>/dist/vuetify.min.css">


<v-app id="app">
  <template>
    <v-expansion-panels>
      <v-expansion-panel @click="click">
        <v-expansion-panel-header>
          <template v-slot:default="{ open }">
            <span>
              <v-progress-circular
                v-if="loading"
                indeterminate
                size="14"
                width="2"
                color="blue"
                class="d-inline-block"
              />
            </span>
            <span>Click me! opened: {{ open }}</span>
          </template>
        </v-expansion-panel-header>
        <v-expansion-panel-content>
          <v-text-field v-for="(item, i) in 1500" :key="i" />
        </v-expansion-panel-content>
      </v-expansion-panel>
    </v-expansion-panels>
  </template>
</v-app>

Answer №1

The issue arises from the fact that the changes triggered by the loading flag (such as displaying the spinner and panel contents) are happening within the same macro tick.

A potential solution is to divide the effects into two distinct groups: (1) toggling the loading flag to show the spinner and open the panel, and (2) toggling a new flag to display the panel contents. This approach allows for shifting the second group of effects to the next macro tick:

  1. Introduce a Boolean flag as a data property and use it to conditionally render the panel contents.

  2. In the click handler, await the next macro tick (e.g., by using a setTimeout() without a timeout parameter).

  3. Toggle the flag created in step 1 to display the panel contents.

<script>
new Vue({
  data: () => ({
    1️⃣
    loadTextfields: false,
  }),
  methods: {
    async click() {
      this.loading = true
      2️⃣
      await new Promise(r => setTimeout(r))
      3️⃣
      this.loadTextfields = true
    }
  }
})
</script>
<v-expansion-panels>
  <v-expansion-panel @click="click">
    ⋮
    <v-expansion-panel-content>
                           1️⃣
      <template v-if="loadTextfields">
        <v-text-field v-for="(item, i) in 1500" :key="i"/>
      </template>
    </v-expansion-panel-content>
  </v-expansion-panel>
</v-expansion-panels>

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data: () => ({
    loading: false,
    loadTextfields: false,
  }),
  methods: {
    async click() {
      console.log('click')
      this.loading = true
      await new Promise(r => setTimeout(r))
      this.loadTextfields = true
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8dfbf8e8cdbfa3f5">[email protected]</a>/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cabcbfafbea3acb38af8e4fce4fb">[email protected]</a>/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="27515242534e415e671509130913">[email protected]</a>/dist/vuetify.min.css">


<v-app id="app">
  <template>
    <v-expansion-panels>
      <v-expansion-panel @click="click">
        <v-expansion-panel-header>
          <template v-slot:default="{ open }">
            <span>
              <v-progress-circular
                v-if="loading"
                indeterminate
                size="14"
                width="2"
                color="blue"
                class="d-inline-block"
              />
            </span>
            <span>Click me! opened: {{ open }}</span>
          </template>
        </v-expansion-panel-header>
        <v-expansion-panel-content>
          <template v-if="loadTextfields">
            <v-text-field v-for="(item, i) in 1500" :key="i"/>
          </template>
        </v-expansion-panel-content>
      </v-expansion-panel>
    </v-expansion-panels>
  </template>
</v-app>

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

Tips on modifying the maxlength attributes for all "field answer" class elements

Looking for some help with adjusting the "maxlength" attribute in a class called "field answer." The current maxlength is set to 250, but I need it changed to 9999. Can someone guide me through this process? <div class="field answer"> &l ...

What is the best way to organize a flatlist for rendering?

I'm struggling with separating some flat-lists into different components. How can I arrange the rendering of the flat-list like the sample form (Picture "Sample UI")? I've tried, but it's not working correctly as it renders flat list A first ...

Transmitting special symbols through Socket.io

I've been working on a small project based on Socketio 0.9 and everything is running smoothly, except for a minor problem with special characters. In the web client, I am creating a dynamic JSON object using JavaScript that is then emitted to the ser ...

Displaying complex JSON data in an HTML format using JavaScript

How can I convert the second array of entities into an HTML format from the JSON data using a for loop or similar method? To access the necessary data, I currently use console.log(data.response[0].entities.urls); $(document).ready(function () { $.getJSO ...

Error encountered with Next.js and Square API: The Fetch API cannot load due to the unsupported URL scheme "webpack-internal"

I encountered an issue while attempting to retrieve stock data from the Square API. injectGlobalHook.js:1648 Fetch API cannot load webpack-internal:///./node_modules/@next/react-dev-overlay/lib/internal/ReactDevOverlay.js. URL scheme "webpack-internal ...

Troubleshooting the issue of autoplay not functioning in HTML5 audio

I'm facing a strange issue with my code - the autoplay feature for audio is not working as expected. Typically, whenever I insert this particular piece of code into a website, the music starts playing automatically. However, it seems to be malfunctio ...

Encountering Error: When Running the Command "npm run dev" it's Showing "missing script: dev" Message

I attempted to set up the SVELT GitHub repository locally by following these steps: https://github.com/fusioncharts/svelte-fusioncharts When I tried to launch it using the "npm run dev" command, I encountered this error: npm ERR! missing script: dev To ...

Different option for key press identification

My JavaScript skills are still at a beginner level and I've come across a bug that's causing me trouble. The issue is with keyCode not working on mobile devices (Chrome). It seems that mobile devices do not support keyCode. I think I could use ...

Skip using bootstrap-vue icons by utilizing the Webpack IgnorePlugin

After analyzing with Webpack bundle analyzer, I discovered that the icons from the bootstrap-vue package are a whopping 535kb in size. Knowing this, I've decided not to utilize them in my project. I attempted to exclude the entire package using a web ...

The HTML element cannot be set within page.evaluate in Node.js Puppeteer

I've run into an issue while using node.js puppeteer, specifically with the page.evaluate method. I'm experiencing difficulties with this part of my code: console.log(response); //This line is valid as it prints a regular string awa ...

Is there a way to use node.js to retrieve a video in mp4 format?

My goal is to allow users to download a video from my AWS S3 bucket in MP4 format: app.get("/download_video", function(req,res) { filename = "s3.xxx.amazon.com/bucketname/folder/video_example.mp4"; // I'm unsure about the next steps }); Whil ...

Ways to customize the appearance of a react-chartist component

I recently created a React JS component that utilizes the amazing react ChartistGraph component. However, I've run into an issue where the default CSS of ChartistGraph seems to be conflicting with my custom styling. While there is plenty of documentat ...

Launching a single modal for multiple posts

I have a collection of posts and for each post, I want the ability to open a modal. However, I am looking for a solution where I can use a single dynamic modal instead of creating multiple modals for each post. Here is the code I currently have: https://j ...

Seeking assistance with transferring jQuery to regular JavaScript and installing on the home screen of an Apple device

Dealing with the issue of iPhone "Bookmark to Homescreen" removing cookies and sessions, I have come up with a jQuery solution. Learn more about this problem here. In essence, by using JavaScript to create add to homescreen kit launch links, you can avoi ...

A guide on expanding an HTML table dynamically with MVC razor syntax

My goal is to dynamically add new rows to a table by following the advice given in this answer on Stack Overflow: Add table row in jQuery I have successfully implemented it for one of my table requirements as seen below: function onAddItem() { $( ...

Attempting to generate a fresh document by duplicating the data from a specific variable

Currently attempting to generate a new csv file within a specific directory. The goal is to save the data of a variable inside the created csv file: handleRequest(req, res) { var svcReq = req.body.svcReq; var csvRecData = JSON.stringify(req.bod ...

What are some effective methods to boost the production build speed of vue cli3?

Looking to create a Vue web app quickly for live preview purposes in production? By skipping unnecessary file optimizations such as compression and chunk creation, we can speed up the build process. What steps should be taken to configure Vue CLI3 for a ...

Encountering a 500 internal server error after deploying due to utilizing getServerSideProps in Next.js

When trying to redeploy my website on Vercel, I added getServerSideProps to my index.js file. However, I encountered an error that I am not familiar with. The program works perfectly on localhost. This is the getServerSideProps code that I added: export a ...

Angular 5 offers the ability to incorporate dynamic checkbox input into your application

Here is my code snippet: <input [type]="'checkbox'" [(ngModel)]="inputValue"> <p>Value: {{ inputValue }}</p> I'm puzzled as to why the value in inputValue remains unchanged. Can anyone shed light on this? I am unable to ...

The deprecated body parser is throwing an error due to the lack of the extended option

I am encountering an issue with my code and I'm not sure how to resolve it. Since I am new to the codebase, I feel completely lost and clueless about what steps to take. body-parser deprecated undefined extended: provide extended option index.js:20:2 ...