7

I want to show a spinner on the first load of my application like: https://devart.withgoogle.com/

I've attempted to do this via the Services module like so:

angular.module('InitialLoad', [])
    .config(function ($httpProvider) {
        $httpProvider.responseInterceptors.push('myHttpInterceptor');
        var spinnerFunction = function (data, headersGetter) {
            $('#loading').fadeIn();
            return data;
        };
        $httpProvider.defaults.transformRequest.push(spinnerFunction);
    })
    .factory('myHttpInterceptor', function ($q, $window) {
        return function (promise) {
            return promise.then(function (response) {
                $('#loading').fadeOut(function(){
                    $(this).remove();
                });
                return response;
            }, function (response) {
               $('#loading').fadeOut(function(){
                    $(this).remove();
                });
                return $q.reject(response);
            });
        };
    });

But there are a number of things wrong with this... first of which is that this doesn't listen for the first load it listens to EVERY request. It also doesn't show and hide the loading as elegant as the way it's been done on DevArt, and I'm using jQuery to hide and show the loading spinner instead of using Angular Animate.

Can anyone help? To clarify this is for the INITIAL app load! And not for showing a spinner on subsequent requests. I use this for that: https://github.com/chieffancypants/angular-loading-bar but I want to show a splash for the app start up which is different.

Cameron
  • 27,963
  • 100
  • 281
  • 483
  • use controllers, they are good to interact with UI – Zafta Aug 18 '14 at 12:58
  • There are many ways to achieve this. You can search on SO and find out many alternatives (i.e. [here](http://stackoverflow.com/questions/17838708/implementing-loading-spinner-using-httpinterceptor-and-angularjs-1-1-5), [here](http://stackoverflow.com/questions/16778140/show-spinner-on-multiple-http-calls-angularjs) ). I would avoid using jQuery DOM manipulation and animations, since there is no meaning in using that for this. – pasine Aug 18 '14 at 13:04
  • Well I've used this: https://github.com/chieffancypants/angular-loading-bar for multiple AJAX requests... but I want to show a splash screen for the **initial load**. Hence the code above. – Cameron Aug 18 '14 at 13:06

2 Answers2

10

If you want to hide your app while AngularJS loads then default your spinner to being displayed using plain HTML, and use ng-cloak to hide the angular portions of the application.

https://docs.angularjs.org/api/ng/directive/ngCloak

Once your app loads you can turn off the spinner using ng-hide/ng-show.

<div ng-controller="TopController">
  <div class="spinner" ng-hide="appLoaded"/>
  <div ng-cloak ng-view>
     ... All Angular view giblets go here...
  </div>
</div>

Here is a working example:

http://jsfiddle.net/kLtzm93x/

chubbsondubs
  • 37,646
  • 24
  • 106
  • 138
  • I'll presume that ng-cloak shows automatically once it's hit in the code without any additional config? But how do I hide the spinner once it's loaded? As your example in your other answer expects a service... – Cameron Aug 19 '14 at 16:05
  • I added an fiddler for your assistance – chubbsondubs Aug 20 '14 at 03:21
  • 2
    So how would I detect the app has loaded? As you're just using a timeout: `$timeout(function() { $scope.loaded = true; }, 5000);` and setting the loaded to true after 5 seconds... but I'd want it to relate to the actual loading of assets (e.g. the app is ready and all data has loaded for the initial view). – Cameron Aug 20 '14 at 08:24
  • Or have I misunderstood the way that timeout is working? Is it counting down 5 seconds **AFTER** everything has loaded? – Cameron Aug 20 '14 at 09:44
  • after 5 seconds run that function. It will load 5 seconds after angular loads which is there just so you can see the spinner. You wouldn't do that in a normal application. Once your controller loads the app has loaded. However, if you also want to make sure the data is loaded then it's my first answer where you wait till the service responds to remove the spinner. – chubbsondubs Aug 20 '14 at 13:46
3

I wouldn't try to do this with an interceptor. It's easy enough to do this with a Controller:

app.controller("TopController", [ "$scope", "SomeService", function($scope, SomeService) {
    $scope.showAppLoader = false;

    $scope.loadApp = function() {
       $scope.showAppLoader = true;
       SomeService.doSomething().success( function(result) {
          $scope.showAppLoader = false;
       });
    };

    $scope.loadApp();
}]);

Then the view:

<div ng-controller="TopController">
   <div class="spinner" ng-show="showAppLoader"></div>
   <div ng-hide="showAppLoader" ng-view"></div>
</div>

The rest of this is just an exercise in CSS.

chubbsondubs
  • 37,646
  • 24
  • 106
  • 138
  • What is SomeService? Should I be passing something in to the controller to check it's loaded? – Cameron Aug 18 '14 at 18:52
  • SomeService is a service you created to load your data from the backend to get your UI started up and why you need to show the spinner in the first place. – chubbsondubs Aug 19 '14 at 02:12
  • Well it'd be the loading of the entire app (e.g. all JS files) rather than an actual data resource. How would I do that? – Cameron Aug 19 '14 at 10:55
  • Added a new answer to account for the fact you want it done while loading the app, but the principle is the same. – chubbsondubs Aug 19 '14 at 14:52