Ash
Ash

Reputation: 574

Load view after a set delay time

I want to create an effect where user wait 2-3 seconds between each page; currently I have in my html page a div with .page-loading class; and in my run script I have the code below;

I also get no errors whatsoever and the loading is constantly showing!

app.run.js

(function() {
    'use strict';
    angular.module('app')
        .run(run);

    run.$inject = ['$window', '$rootScope', '$timeout'];

    function run($window, $rootScope, $timeout) {

        //Loading
        var delay = 1000;

        $rootScope
            .$on('$stateChangeStart',
                function(event, toState, toParams, fromState, fromParams) {
                    $timeout(function() {
                        $(".page-loading").removeClass("ng-hidden");
                        $(".page").addClass("ng-hidden");
                    }, delay);
                });

        $rootScope
            .$on('$stateChangeSuccess',
                function(event, toState, toParams, fromState, fromParams) {
                    $timeout(function() {
                        $(".page-loading").addClass("ng-hidden");
                        $(".page").removeClass("ng-hidden");
                    }, delay);
                });



    };
})();

My View code

<div class="page-loading ng-hidden">Loading...</div>
<div ui-view class="page"></div>

Upvotes: 0

Views: 3547

Answers (1)

tasseKATT
tasseKATT

Reputation: 38490

Not sure if you have your own ng-hidden class, otherwise you should use ng-hide.

Other than that, there are a few timing issues in your code.

Unless you have states that take really long to load (for example if you use resolve) there won't be much delay at all between the events $stateChangeStart and $stateChangeSuccess. This means that the two functions passed to $timeout will fire right after each other and for example the loader element will have a class removed then instantly added again.

Below is an example with comments of what I believe you are trying to achieve.

var hideClass = 'ng-hide',
  delay = 1000,
  firstChangeStartt = false,
  firstContentLoaded = false,
  timer;

$rootScope.$on('$stateChangeStart',
  function(event, toState, toParams, fromState, fromParams) {

    // Remove this if you want the loader + delayed view behavior when first entering the page
    if (!firstChangeStartt) {
      firstChangeStartt = true;
      return;
    }

    // Cancel the ongoing timer (if any)
    // This is used not to get weird behaviors if you change state before the previous has finished loading
    $timeout.cancel(timer);

    // Show the loader and hide the old view as soon as a state change has started
    $(".page-loading").removeClass(hideClass);
    $('.page').addClass(hideClass);
  });

// Use '$viewContentLoaded' instead of '$stateChangeSuccess'.
// When '$stateChangeSuccess' fires the DOM has not been rendered and you cannot directly query the elements from the new HTML
// When '$viewContentLoaded' fires the new DOM has been rendered
$rootScope.$on('$viewContentLoaded',
  function(event, toState, toParams, fromState, fromParams) {

    // Remove this if you want the loader + delayed view behavior when first entering the page
    if (!firstContentLoaded) {
      firstContentLoaded = true;
      return;
    }

    $timeout.cancel(timer);

    // Hide the new view as soon as it has rendered
    var page = $('.page');
    page.addClass(hideClass);

    // Hide the loader and show the new view after a delay
    // Pass false as the third argument to prevent the digest loop from starting (since you are just modifying CSS there is no reason for Angular to perform dirty checking in this example)
    timer = $timeout(function() {

      page.removeClass(hideClass);
      $(".page-loading").addClass(hideClass);

    }, delay, false);
  });

If you have any questions just let me know.

Demo: http://plnkr.co/edit/bpMvgFEArfiJQ5EgIrfG?p=preview

Upvotes: 2

Related Questions