John Abraham
John Abraham

Reputation: 18791

Directive that serves as a loading screen

I'm making a tool that has a 2~5 second load, depending on the page & server. I want to create a directive that will show on every route change and fadeout after a page has been fully rendered.

Stack:

Yeoman, Grunt, Bower, jQuery, Angular, & Firebase

Directive

app.directive('overlay', function() {
    return {
        restrict: 'E',
        template: '<div class="overlay-jordan"></div>',

        link:function ($scope) {

          }
      };
  });

CSS

.overlay-jordan {
  opacity: 1;
  position: absolute;
  left:0;
  right:0;
  top:0;
  bottom:0;
  background: url(../images/jordan-overlay.png) no-repeat center center;
  background-size: cover;
  z-index: 99999;
}

Upvotes: 0

Views: 270

Answers (1)

Olivier-J
Olivier-J

Reputation: 26

I forget where i found this code, but it works nice for me.

You can do it with interceptors on $httpProvider.

angular.module("app", [])
    .constant('_START_REQUEST_', '_START_REQUEST_')
    .constant('_END_REQUEST_', '_END_REQUEST_')
    .config(['$httpProvider', '_START_REQUEST_', '_END_REQUEST_', function ($httpProvider, _START_REQUEST_, _END_REQUEST_) {
        var $http,
            interceptor = ['$q', '$injector', function ($q, $injector) {
                var rootScope, location;

                function success(response) {
                    // get $http via $injector because of circular dependency problem
                    $http = $http || $injector.get('$http');
                    // don't send notification until all requests are complete
                    if ($http.pendingRequests.length < 1) {
                        // get $rootScope via $injector because of circular dependency problem
                        rootScope = rootScope || $injector.get('$rootScope');
                        // send a notification requests are complete
                        rootScope.$broadcast(_END_REQUEST_);
                    }
                    return response;
                }

                function error(response) {
                    // get $http via $injector because of circular dependency problem
                    $http = $http || $injector.get('$http');
                    // don't send notification until all requests are complete
                    if ($http.pendingRequests.length < 1) {
                        // get $rootScope via $injector because of circular dependency problem
                        rootScope = rootScope || $injector.get('$rootScope');
                        // send a notification requests are complete
                        rootScope.$broadcast(_END_REQUEST_);
                    }
                    return $q.reject(response);
                }

                return function (promise) {
                    // get $rootScope via $injector because of circular dependency problem
                    rootScope = rootScope || $injector.get('$rootScope');
                    // send notification a request has started
                    rootScope.$broadcast(_START_REQUEST_);
                    return promise.then(success, error);
                }
            }];

        $httpProvider.responseInterceptors.push(interceptor);
    }])
    // Loading directive
    .directive('loadingWidget', ['_START_REQUEST_', '_END_REQUEST_', function (_START_REQUEST_, _END_REQUEST_) {
        return {
            restrict: "A",
            link: function (scope, element) {
                // hide the element initially
                element.hide();

                scope.$on(_START_REQUEST_, function () {
                    // got the request start notification, show the element
                    element.show();
                });

                scope.$on(_END_REQUEST_, function () {
                    // got the request end notification, hide the element
                    element.hide();
                });
            }
        };
    }])

And in your main html page, just declare your loading content

<div id="loadingWidget" loading-widget>
    <div class="loadingContent">
        <p>
            Loading ...
        </p>
    </div>
</div>

Upvotes: 1

Related Questions