ArdAtak
ArdAtak

Reputation: 239

Displaying a loading animation during a vue js function

A simple show and hide on the loading element is failing during the Vue js function execution.

I have a vue js function which will do some things and update the data when it's done. I'm trying to show a loading animation during this process. I've dummied the process down to a simple loop for the purposes of this discussion to eliminate all other issues (i.e ajax, async, etc.).

My HTMl for the button looks like this:

<button type="button" v-on:click="DoStuff()">Do Stuff</button>

My vue js code looks like this:

var client = new Vue({
    el: '#client',
    data: {
        someData: []
},
methods: {
    DoStuff: function() {

        //Show Loader
        $(".loader").show();

        //Waste 5 seconds
        for (var i = 0; i < 100000000; i++) {
            var x = i;
        }

        //Hide loader
        $(".loader").hide();

        // let me know it's done.
        alert('cool');
    }

The loader never shows. If I comment out the hide command, the loader show up AFTER the alert. Makes me think some sort of async operation is going on under the hood but I'm not doing async stuff.

Upvotes: 3

Views: 13528

Answers (4)

ArdAtak
ArdAtak

Reputation: 239

Thanks Everyone. I have to focus on a more important feature that came up. But I just wanted to share what I've gleamed. This is not a (or the) final answer but it explains the problem and the correct approach.

The problem was correctly identified by Andrew Lohr as is further explained here: jQuery hide() and show() not immediately run when reversed later in the function

The best (but not only) solution would be use an event bus as mentioned by perellorodrigo here: https://flaviocopes.com/vue-components-communication/

I will post my final solution when I get around to it.

Upvotes: -3

Isaac Vidrine
Isaac Vidrine

Reputation: 1666

You don't need to use jQuery to set and hide elements on the page based on a condition, in fact that kind of defeats the purpose of what VueJS and other front end javascript frameworks are used for.

First you should add a property called loading to your data object

data: {
   someData: [],
   loading: false
}

Then, in your doStuff function, remove the jquery lines and set the loading property accordingly

methods: {
    doStuff: function() {
        //Show Loader
        this.loading = true;

        //Waste 5 seconds
        setTimeout(() => {
           this.loading = false;
        }, 5000)
    }
}

Finally, in your view, add this line

<div v-if="loading">Loading some data</div>

Ill end this by saying that I also think your snippet is a little messed up. the methods property should be inside the Vue instance definition.

var client = new Vue({
    el: '#client',
    data: {
        someData: [],
        loading: false
    },
    methods: {
       doStuff: function() {
          //Show Loader
          this.loading = true;

          //Waste 5 seconds
          setTimeout(() => {
            this.loading = false;
          }, 5000)
       }

   }
}

Upvotes: 8

Michael Mano
Michael Mano

Reputation: 3440

Don't use jquery. You can so this with vuejs.


var client = new Vue({
    el: '#client',
    data: {
        someData: [],
        loading: false,
},
methods: {
    DoStuff() {

        //Show Loader
        this.loading = true;

        //Waste 5 seconds

        //Hide loader
        this.loading = true;

        // let me know it's done.
        alert('cool');
    }

And your HTML.

<div class="loading" v-if="loading">
    Loading....
</div>
<div v-else>
The rest of your website 
</div>

Upvotes: 2

perellorodrigo
perellorodrigo

Reputation: 536

It's better to not mix with JQuery, just use Vue conditional displaying instead (v-show).

In your loader:

<div class="loader" v-show="loading"></div>

In your Vue code:

var client = new Vue({
    el: '#client',
    data: {
        someData: [],
        loading: false
},
methods: {
    DoStuff: function() {

        this.loading = true;

        //Waste 5 seconds
        for (var i = 0; i < 100000000; i++) {
            var x = i;
        }

        this.loading = false;

        // let me know it's done.
        alert('cool');
    }

Upvotes: 0

Related Questions