Adding an AngularJS AJAX busy indicator to the RAW stack

With the typical AngularJS SPA application there are lots of AJAX calls going on to retrieve data from the server. This sometimes results in a view that appears empty to the user. The page is rendered without any data as that is still being loaded. This also happens on the movie page in the demo application. While technically completely understandable it can be confusing to an end user not seeing the expected data. While we can’t make the data appear any faster we can show the fact that the application is doing something in the background so the user knows there is some activity still ongoing.


Intercepting AngularJS AJAX requests

In AngularJS all AJAX request are done using the $http service. This $http service can configured a number of different ways using the $httpProvider service provider. One of the things we can do using the $httpProvider is add request/response interceptors by adding an interceptor function to the $httpProvider.interceptors array. This will fire once for each request being done and again for each response received. Using this pair and a simple counter we can see when the first request starts and when the last request is done.


   1: module.config(function ($httpProvider) {

   2:     $httpProvider.interceptors.push(function ($q, $rootScope) {

   3:         var requests = 0;


   5:         function show() {

   6:             if (!requests) {

   7:                 $rootScope.$broadcast("ajax-start");

   8:             }

   9:             requests++;

  10:         }


  12:         function hide() {

  13:             requests--;

  14:             if (!requests) {

  15:                 $rootScope.$broadcast("ajax-stop");

  16:             }

  17:         }


  19:         return {

  20:             'request': function (config) {

  21:                 show();

  22:                 return $q.when(config);

  23:             }, 'response': function (response) {

  24:                 hide();

  25:                 return $q.when(response);

  26:             }, 'responseError': function (rejection) {

  27:                 hide();

  28:                 return $q.reject(rejection);

  29:             }

  30:         };

  31:     });

  32: });


Being able to intercept each request/response is nice but that still leaves us with the part of updating the user interface. Doing so in an http interceptor is not the right thing. But what we can do broadcast events using the $rootScope and have something else subscribe to those events. One really nice place to do that is in an AngularJS directive. We can simply add that directive to the part of the UI we want to show/hide and we are all done. In this case I have used a simple spinning gif.


   1: <div ng-app="myApp">

   2:     <div raw-ajax-busy-indicator="" class="ajax-busy-indicator">

   3:     </div>

   4:     <div ng-view=""></div>

   5: </div>


   1: .ajax-busy-indicator {

   2:     position: fixed;

   3:     top: 50px;

   4:     right: 15px;

   5:     background-image: url("/Content/busy_indicator.gif");

   6:     height: 48px;

   7:     width: 48px;

   8: }


   1: module.directive("rawAjaxBusyIndicator", function () {

   2:     return {

   3:         link: function (scope, element) {

   4:             scope.$on("ajax-start", function () {

   5:       ;

   6:             });

   7:             scope.$on("ajax-stop", function () {

   8:                 element.hide();

   9:             });

  10:         }

  11:     };

  12: });


Try it

The running application can be found here and the source on GitHub here.



A nice and simple $http interceptor with a completely reusable directive. Sweet :-)


Index of posts on the RAW stack

See here for more posts on the RAW stack.

One thought on “Adding an AngularJS AJAX busy indicator to the RAW stack

  1. Thanks for the useful post! Have you looked at your code snippet styling recently? Each line has an unnecessary line number indicator, and an enormous space above and below making it impossible to read as code. I’d suggest simplifying just give me some basic fixed-width font and properly indented code and keep it simple.

Leave a Reply

Your email address will not be published. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>