Search code examples
ajaxvue.jsvue-resourcevue-component

How to know when all child components are loaded in vue.js


I have a vue.js app where there are several child components like this:

<main-app>
   <child-component></child-component>
   <child-component></child-component>
   <child-component></child-component>
...
</main>

When the page is loaded, I can use ready hook to know that the components are done loading. Now, these components are filled using ajax data and they can be manually updated by clicking a button. I can get data from each child-component by using broadcast and dispatch methods. But I want to show the user a preloader when s/he clicks on the button and hide it when all ajax requests are finished. For this I need to know that all child-components are finished loading. Which I cannot do for last 4-5 hours. Google and SO didn't help much.

I have also tried using jQuery's ajaxStop but it doesn't seem to work with vue-resource. Can anyone please help me?


Solution

  • I needed to do something similar once and what I ended up doing (besides using v-cloak to display the app once vue rendering is done) was tracking whether each require variable in data already had data (or not) and only then, "display" the app (for this I used an internal flag to control whether to display the app or a loading message).

    It was something similar to this (this uses underscore.js):

    var app = new Vue({
        el: 'body',
        data: {
            data1: [],
            data2: [],
            data3: []
        },
        ready: function() {
            this.showApp();
    
            // Data 1
            $.getJSON('/path-to/data1', function(data) {
                app.$set('data1', data);
                app.showApp();
            });
    
            // Data 2
            $.getJSON('/path-to/data2', function(data) {
                app.$set('data2', data);
                app.showApp();
            });
    
            // Data 3
            $.getJSON('/path-to/data3', function(data) {
                app.$set('data3', data);
                app.showApp();
            });
        },
        methods: {
            showApp: function() {
                // Check if all data was loaded
                var requiredData = _.every(['data1', 'data2', 'data3'], function(el) {
                    return _.size(this[el]) > 0;
                }, this);
    
                // If it was, enable the app
                if (requiredData) {
                    $(this.$els.loading).hide();
                    $(this.$els.app).fadeIn();
                }
            }
        }
    });
    

    Since you are using components, you will have to use events to fire the showApp method on the main app.