AngularJS: Loading spinner during view state changes and API calls

AngularJS allows developers to create powerful web applications in a seamless, single-page experience. However, during state changes and API calls it’s important to indicate to the visitor that the next view or API response is still processing. Without a loading spinner it can feel as though nothing is happening while back-end API calls complete and Angular re-renders the view accordingly.

Here is how you can add a loading spinner to your application in under 10 minutes:

loadingspinner

First we will create the service: service.interceptor.js

'use strict';

/**
 * # APIInterceptor
 * Service Factory that will be an interceptor in order to show/hide the
 * spinner when making API calls
 */
angular.module('myApp')
.service('APIInterceptor', function($q, $rootScope, $log, $location, $window) {
    var service = this;

    service.request = function(config) { 
        $log.debug("service.request:Show Spinner");
        
        if (config.url.indexOf('.html') < 0) {
            // for hide spinner in background service calls 
            ($rootScope.bgHideSpinner) ? ($rootScope.showSpinner = true) : ($rootScope.bgHideSpinner = true);
        }
        
        //$log.debug(config);
        return config;
    };

    service.requestError = function(config) {
        $log.debug("service.requestError:Show Spinner");
        $rootScope.showSpinner = true;
        //$log.debug(config);
        return config;
    };

    service.response = function(response) {
        $log.debug("service.response:Hide Spinner");
        if (response.config.url.indexOf('.html') < 0) {
        	$rootScope.showSpinner = false;
        }
        //$log.debug(response);
        return response;
    };

    service.responseError = function(response) {
        $log.debug("service.responseError:Hide Spinner");
        $rootScope.showSpinner = false;

        return $q.reject(response); /* without this reject the error goes into success handler */

    }})

Then we will include the service in app.js

config(['$httpProvider', function($httpProvider) {

	$httpProvider.interceptors.push('APIInterceptor');	
	
}

Then we will want to include the both the service and spinner HTML in our index.html

<script type="text/javascript" src="app/services/api.interceptor.js"></script>
<div ng-show="($root.EachScreenLoad || $root.showSpinner) && !$root.preFetch" class="loader-screen">
    <div ng-show="($root.EachScreenLoad || $root.showSpinner)" class="loader"></div>
</div>

Lastly, we will include the styling / CSS for the spinner in app.css

.loader-screen {
    width: 100%;
    height: 100%;
    background:rgba(0,0,0,0.3); 
    position: fixed;
    top: 0;
    left: 0;
    z-index: 9990; 
}

.spinner,.loader{
  margin: auto;
  font-size: 10px;
  position: relative;
  text-indent: -9999em;
  border-top: 1.1em solid rgba(255, 255, 255, 0.4);
  border-right: 1.1em solid rgba(255, 255, 255, 0.4);
  border-bottom: 1.1em solid rgba(255, 255, 255, 0.4);
  border-left: 1.1em solid #ffffff;
  -webkit-transform: translateZ(0);
  -ms-transform: translateZ(0);
  transform: translateZ(0);
  -webkit-animation: load8 1.1s infinite linear;
  animation: load8 1.1s infinite linear;
  top: calc(50% - 5em);
   -webkit-transform: translate(0,-50%);
  -ms-transform: translate(0,-50%);
   transform: translate(0,-50%);
}
.loader,
.loader:after {
  border-radius: 50%;
  width: 10em;
  height: 10em;
}
@-webkit-keyframes load8 {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@keyframes load8 {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

And that is how you add a loading spinner to state changes and API calls in your Angular application.

Categories AngularJS

Leave a Reply