Show spinner GIF during an $http request in AngularJS?

AngularjsAjaxBusyindicator

Angularjs Problem Overview


I am using the $http service of AngularJS to make an Ajax request.

How can a spinner GIF (or another type of busy indicator) be shown while the Ajax request is executing?

I don't see anything like an ajaxstartevent in the AngularJS documentation.

Angularjs Solutions


Solution 1 - Angularjs

This really depends on your specific use case, but a simple way would follow a pattern like this:

.controller('MainCtrl', function ( $scope, myService ) {
  $scope.loading = true;
  myService.get().then( function ( response ) {
    $scope.items = response.data;
  }, function ( response ) {
    // TODO: handle the error somehow
  }).finally(function() {
    // called no matter success or failure
    $scope.loading = false;
  });
});

And then react to it in your template:

<div class="spinner" ng-show="loading"></div>
<div ng-repeat="item in items>{{item.name}}</div>

Solution 2 - Angularjs

Here are the current past AngularJS incantations:

angular.module('SharedServices', [])
    .config(function ($httpProvider) {
        $httpProvider.responseInterceptors.push('myHttpInterceptor');
        var spinnerFunction = function (data, headersGetter) {
            // todo start the spinner here
            //alert('start spinner');
        	$('#mydiv').show();
            return data;
        };
        $httpProvider.defaults.transformRequest.push(spinnerFunction);
    })
// register the interceptor as a service, intercepts ALL angular ajax http calls
    .factory('myHttpInterceptor', function ($q, $window) {
        return function (promise) {
            return promise.then(function (response) {
                // do something on success
                // todo hide the spinner
                //alert('stop spinner');
            	$('#mydiv').hide();
                return response;

            }, function (response) {
                // do something on error
                // todo hide the spinner
                //alert('stop spinner');
            	$('#mydiv').hide();
                return $q.reject(response);
            });
        };
    });

//regular angular initialization continued below....
angular.module('myApp', [ 'myApp.directives', 'SharedServices']).
//.......

Here is the rest of it (HTML / CSS)....using

$('#mydiv').show(); 
$('#mydiv').hide(); 

to toggle it. NOTE: the above is used in the angular module at beginning of post

#mydiv {  
    position:absolute;
    top:0;
    left:0;
    width:100%;
    height:100%;
    z-index:1000;
    background-color:grey;
    opacity: .8;
 }

.ajax-loader {
    position: absolute;
    left: 50%;
    top: 50%;
    margin-left: -32px; /* -1 * image width / 2 */
    margin-top: -32px;  /* -1 * image height / 2 */
    display: block;     
}

<div id="mydiv">
    <img src="lib/jQuery/images/ajax-loader.gif" class="ajax-loader"/>
</div>

Solution 3 - Angularjs

Here's a version using a directive and ng-hide.

This will show the loader during all calls via angular's $http service.

In the template:

<div class="loader" data-loading></div>

directive:

angular.module('app')
  .directive('loading', ['$http', function ($http) {
    return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        scope.isLoading = function () {
          return $http.pendingRequests.length > 0;
        };
        scope.$watch(scope.isLoading, function (value) {
          if (value) {
            element.removeClass('ng-hide');
          } else {
            element.addClass('ng-hide');
          }
        });
      }
    };
}]);

by using the ng-hide class on the element, you can avoid jquery.


Customize: add an interceptor

If you create a loading-interceptor, you can show/hide the loader based on a condition.

directive:

var loadingDirective = function ($rootScope) {
  return function ($scope, element, attrs) {
      $scope.$on("loader_show", function () {
          return element.removeClass('ng-hide');
      });
      return $scope.$on("loader_hide", function () {
          return element.addClass('ng-hide');
      });
  };
};

interceptor:

  • for example: don't show spinner when response.background === true;
  • Intercept request and/or response to set $rootScope.$broadcast("loader_show"); or $rootScope.$broadcast("loader_hide");

more info on writing an interceptor

Solution 4 - Angularjs

If you are using ngResource, the $resolved attribute of an object is useful for loaders:

For a resource as follows:

var User = $resource('/user/:id', {id:'@id'});
var user = User.get({id: 1})

You can link a loader to the $resolved attribute of the resource object:

<div ng-hide="user.$resolved">Loading ...</div>

Solution 5 - Angularjs

https://github.com/wongatech/angular-http-loader is a good project for this.

Example here http://wongatech.github.io/angular-http-loader/

The code below shows a template example/loader.tpl.html when a request is happening.

<div ng-http-loader template="example/loader.tpl.html"></div>

Solution 6 - Angularjs

Just discovered the angular-busy directive that shows a little loader depending on some async call.

For example, if you have to make a GET, reference the promise in your $scope,

$scope.req = $http.get('http://google.fr');

and call it like so :

<div cg-busy="req"></div>

Here is the GitHub.

You can also install it using bower (don't forget to update your project dependencies):

bower install angular-busy --save

Solution 7 - Angularjs

For page loads and modals, the easiest way is to use the ng-show directive and use one of the scope data variables. Something like:

ng-show="angular.isUndefined(scope.data.someObject)".

Here, while someObject is undefined, the spinner will show. Once the service returns with data and someObject is populated, the spinner will return to its hidden state.

Solution 8 - Angularjs

If you're wrapping your api calls within a service/factory, then you can track the loading counter there (per answer and excellent simultaneous suggestion by @JMaylin), and reference the loading counter via a directive. Or any combination thereof.

API WRAPPER

yourModule
	.factory('yourApi', ['$http', function ($http) {
		var api = {}
		
		//#region ------------ spinner -------------

		// ajax loading counter
		api._loading = 0;

		/**
		 * Toggle check
		 */
		api.isOn = function () { return api._loading > 0; }

		/**
		 * Based on a configuration setting to ignore the loading spinner, update the loading counter
		 * (for multiple ajax calls at one time)
		 */
		api.spinner = function(delta, config) {
			// if we haven't been told to ignore the spinner, change the loading counter
			// so we can show/hide the spinner

			if (NG.isUndefined(config.spin) || config.spin) api._loading += delta;

			// don't let runaway triggers break stuff...
			if (api._loading < 0) api._loading = 0;

			console.log('spinner:', api._loading, delta);
		}
		/**
		 * Track an ajax load begin, if not specifically disallowed by request configuration
		 */
		api.loadBegin = function(config) {
			api.spinner(1, config);
		}
		/**
		 * Track an ajax load end, if not specifically disallowed by request configuration
		 */
		api.loadEnd = function (config) {
			api.spinner(-1, config);
		}
		
		//#endregion ------------ spinner -------------

		var baseConfig = {
			method: 'post'
			// don't need to declare `spin` here
		}

		/**
		 * $http wrapper to standardize all api calls
		 * @param args stuff sent to request
		 * @param config $http configuration, such as url, methods, etc
		 */
		var callWrapper = function(args, config) {
			var p = angular.extend(baseConfig, config); // override defaults
			
			// fix for 'get' vs 'post' param attachment
			if (!angular.isUndefined(args)) p[p.method == 'get' ? 'params' : 'data'] = args;

			// trigger the spinner
			api.loadBegin(p);
			
			// make the call, and turn of the spinner on completion
			// note: may want to use `then`/`catch` instead since `finally` has delayed completion if down-chain returns more promises
			return $http(p)['finally'](function(response) {
				api.loadEnd(response.config);
				return response;
			});
		}
		
		api.DoSomething = function(args) {
			// yes spinner
			return callWrapper(args, { cache: true });
		}
		api.DoSomethingInBackground = function(args) {
			// no spinner
			return callWrapper(args, { cache: true, spin: false });
		}
		
		// expose
		return api;
	});

SPINNER DIRECTIVE

(function (NG) {
	var loaderTemplate = '<div class="ui active dimmer" data-ng-show="hasSpinner()"><div class="ui large loader"></div></div>';

	/**
	 * Show/Hide spinner with ajax
	 */
	function spinnerDirective($compile, api) {
		return {
			restrict: 'EA',
			link: function (scope, element) {
				// listen for api trigger
				scope.hasSpinner = api.isOn;

				// attach spinner html
				var spin = NG.element(loaderTemplate);
				$compile(spin)(scope); // bind+parse
				element.append(spin);
			}
		}
	}

	NG.module('yourModule')
		.directive('yourApiSpinner', ['$compile', 'yourApi', spinnerDirective]);
})(angular);

USAGE

<div ng-controller="myCtrl" your-api-spinner> ... </div>

Solution 9 - Angularjs

This is the easiest way to add a spinner i guess:-

You can use ng-show with the div tag of any one of these beautiful spinners http://tobiasahlin.com/spinkit/ {{This is not my page}}

and then you can use this kind of logic

//ajax start
    $scope.finderloader=true;
    
          $http({
    method :"POST",
    url : "your URL",
  data: { //your data
     
     }
  }).then(function mySucces(response) {
    $scope.finderloader=false;
      $scope.search=false;          
    $scope.myData =response.data.records;
  });
     
    //ajax end 
    

<div ng-show="finderloader" class=spinner></div>
//add this in your HTML at right place

Solution 10 - Angularjs

Based on Josh David Miller response:

  <body>
  <header>
  </header>
<div class="spinner" ng-show="loading">
  <div class="loader" ></div>
</div>

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

<footer>
</footer>

</body>

Add this css:

    .loader {
  border: 16px solid #f3f3f3;
  border-radius: 50%;
  border-top: 16px solid #3498db;
  border-bottom : 16px solid black;
  width: 80px;
  height: 80px;
  -webkit-animation: spin 2s linear infinite;
  animation: spin 2s linear infinite;
  position: absolute;
  top: 45%;
  left: 45%;
}

@-webkit-keyframes spin {
  0% { -webkit-transform: rotate(0deg); }
  100% { -webkit-transform: rotate(360deg); }
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}


.spinner{
  width: 100%;
height: 100%;
z-index: 10000;
position: absolute;
top: 0;
left: 0;
margin: 0 auto;
text-align: center;
vertical-align: middle;
background: white;
opacity: 0.6;
}

And just in your angular add:

$rootScope.loading = false; $rootScope.loading = true; -> when $http.get ends.

Solution 11 - Angularjs

Sharing my version of the great answer from @bulltorious, updated for newer angular builds (I used version 1.5.8 with this code), and also incorporated @JMaylin's idea of using a counter so as to be robust to multiple simultaneous requests, and the option to skip showing the animation for requests taking less than some minimum number of milliseconds:

var app = angular.module('myApp');
var BUSY_DELAY = 1000; // Will not show loading graphic until 1000ms have passed and we are still waiting for responses.

app.config(function ($httpProvider) {
  $httpProvider.interceptors.push('busyHttpInterceptor');
})
  .factory('busyHttpInterceptor', ['$q', '$timeout', function ($q, $timeout) {
    var counter = 0;
    return {
      request: function (config) {
        counter += 1;
        $timeout(
          function () {
            if (counter !== 0) {
              angular.element('#busy-overlay').show();
            }
          },
          BUSY_DELAY);
        return config;
      },
      response: function (response) {
        counter -= 1;
        if (counter === 0) {
          angular.element('#busy-overlay').hide();
        }
        return response;
      },
      requestError: function (rejection) {
        counter -= 1;
        if (counter === 0) {
          angular.element('#busy-overlay').hide();
        }
        return rejection;
      },
      responseError: function (rejection) {
        counter -= 1;
        if (counter === 0) {
          angular.element('#busy-overlay').hide();
        }
        return rejection;
      }
    }
  }]);

Solution 12 - Angularjs

You can use angular interceptor to manage http request calls

  <div class="loader">
    <div id="loader"></div>
  </div>

<script>
    var app = angular.module("myApp", []);

    app.factory('httpRequestInterceptor', ['$rootScope', '$location', function ($rootScope, $location) {
        return {
            request: function ($config) {
                $('.loader').show();
                return $config;
            },
            response: function ($config) {
                $('.loader').hide();
                return $config;
            },
            responseError: function (response) {
                return response;
            }
        };
    }]);

    app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider',
        function ($stateProvider, $urlRouterProvider, $httpProvider) {
            $httpProvider.interceptors.push('httpRequestInterceptor');
        }]);

</script>

https://stackoverflow.com/a/49632155/4976786

Solution 13 - Angularjs

Simple way without interceptors or jQuery

This is a simple way to show a spinner that does not require a third-party library, intercepters, or jQuery.

In the controller, set and reset a flag.

function starting() {
    //ADD SPINNER
    vm.starting = true;
    $http.get(url)
      .then(function onSuccess(response) {
        vm.data = response.data;
    }).catch(function onReject(errorResponse) {
        console.log(errorResponse.status);
    }).finally(function() {
        //REMOVE SPINNER
        vm.starting = false;
    });
};

In the HTML, use the flag:

<div ng-show="vm.starting">
    <img ng-src="spinnerURL" />
</div>

<div ng-hide="vm.starting">
    <p>{{vm.data}}</p>
</div>

The vm.starting flag is set true when the XHR starts and cleared when the XHR completes.

Solution 14 - Angularjs

This works well for me:

HTML:

  <div id="loader" class="ng-hide" ng-show="req.$$state.pending">
    <img class="ajax-loader" 
         width="200" 
         height="200" 
         src="/images/spinner.gif" />
  </div>

Angular:

  $scope.req = $http.get("/admin/view/"+id).success(function(data) {          
      $scope.data = data;
  });

While the promise returned from $http is pending, ng-show will evaluate it to be "truthy". This is automatically updated once the promise is resolved... which is exactly what we want.

Solution 15 - Angularjs

Used following intercepter to show loading bar on http request

'use strict';
appServices.factory('authInterceptorService', ['$q', '$location', 'localStorage','$injector','$timeout', function ($q, $location, localStorage, $injector,$timeout) {

var authInterceptorServiceFactory = {};
var requestInitiated;

//start loading bar
var _startLoading = function () {
   console.log("error start loading");
   $injector.get("$ionicLoading").show();
  
}

//stop loading bar
var _stopLoading = function () {
    $injector.get("$ionicLoading").hide();
}

//request initiated
var _request = function (config) {
     requestInitiated = true;
    _startLoading();
    config.headers = config.headers || {};
    var authDataInitial = localStorage.get('authorizationData');
    if (authDataInitial && authDataInitial.length > 2) {
        var authData = JSON.parse(authDataInitial);
        if (authData) {
            config.headers.Authorization = 'Bearer ' + authData.token;
        }
    }
    return config;
}

//request responce error
var _responseError = function (rejection) {
   _stopLoading();
    if (rejection.status === 401) {
        $location.path('/login');
    }
    return $q.reject(rejection);
}
                                           
//request error
var _requestError = function (err) {
   _stopLoading();
   console.log('Request Error logging via interceptor');
   return err;
}

//request responce
var _response = function(response) {
    requestInitiated = false;

   // Show delay of 300ms so the popup will not appear for multiple http request
   $timeout(function() {
			
		if(requestInitiated) return;
		_stopLoading();
		console.log('Response received with interceptor');
			
	},300);

return response;
}
                                           
                                       

authInterceptorServiceFactory.request = _request;
authInterceptorServiceFactory.responseError = _responseError;
authInterceptorServiceFactory.requestError = _requestError;
authInterceptorServiceFactory.response = _response;

return authInterceptorServiceFactory;
}]);

Solution 16 - Angularjs

.factory('authHttpResponseInterceptor', ['$q', function ($q) {
		return {
			request: function(config) {
				angular.element('#spinner').show();
				return config;
			},
			response : function(response) {
				angular.element('#spinner').fadeOut(3000);
				return response || $q.when(response);
			},
			responseError: function(reason) {
				angular.element('#spinner').fadeOut(3000);
				return $q.reject(reason);
			}
		};
	}]);



 .config(['$routeProvider', '$locationProvider', '$translateProvider', '$httpProvider',
    		function ($routeProvider, $locationProvider, $translateProvider, $httpProvider) {
    			$httpProvider.interceptors.push('authHttpResponseInterceptor');
    }
]);

in your Template
<div id="spinner"></div>


css   

#spinner,
#spinner:after {
  border-radius: 50%;
  width: 10em;
  height: 10em;
  background-color: #A9A9A9;
  z-index: 10000;
  position: absolute;
  left: 50%;
  bottom: 100px;
}
@-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);
  }
}
  

Solution 17 - Angularjs

create directive with this code:

$scope.$watch($http.pendingRequests, toggleLoader);

function toggleLoader(status){
  if(status.length){
    element.addClass('active');
  } else {
    element.removeClass('active');
  }
}

Solution 18 - Angularjs

Another solution to show loading between different url changes is:

$rootScope.$on('$locationChangeStart', function() {
  $scope.loading++;
});

$rootScope.$on('$locationChangeSuccess', function() {
  $timeout(function() {
    $scope.loading--;
  }, 300);
});

And then in the markup just toggle the spinner with ng-show="loading".

If you want to display it on ajax requests just add $scope.loading++ when the request starts and when it ends add $scope.loading--.

Solution 19 - Angularjs

You can try something like this as well:

Create directive :

myApp.directive('loader', function () {
    return {
        restrict: 'A',
        scope: {cond: '=loader'},
        template: '<span ng-if="isLoading()" class="soft"><span class="fa fa-refresh fa-spin"></span></span>',
        link: function (scope) {
            scope.isLoading = function() {
                var ret = scope.cond === true || (
                        scope.cond &&
                        scope.cond.$$state &&
                        angular.isDefined(scope.cond.$$state.status) &&
                        scope.cond.$$state.status === 0
                    );
                return ret;
            }
        }
    };
}); 

Then you add something like this to mainCtrl

    // Return TRUE if some request is LOADING, else return FALSE
    $scope.isLoading = function() {
        return $http.pendingRequests.length > 0;
    };

And HTML can looks like this:

<div class="buttons loader">
    <span class="icon" loader="isLoading()"></span>
</div>

Solution 20 - Angularjs

The following way will take note of all requests, and hide only once all requests are done:

app.factory('httpRequestInterceptor', function(LoadingService, requestCount) {
    return {
        request: function(config) {
            if (!config.headers.disableLoading) {
                requestCount.increase();
                LoadingService.show();
            }
            return config;
        }
    };
}).factory('httpResponseInterceptor', function(LoadingService, $timeout, error, $q, requestCount) {
    function waitAndHide() {
        $timeout(function() {
            if (requestCount.get() === 0){
                LoadingService.hide();
            }
            else{
                waitAndHide();
            }
        }, 300);
    }

    return {
        response: function(config) {
            requestCount.descrease();
            if (requestCount.get() === 0) {
                waitAndHide();
            }
            return config;
        },
        responseError: function(config) {
            requestCount.descrease();
            if (requestCount.get() === 0) {
                waitAndHide();
            }
            var deferred = $q.defer();
            error.show(config.data, function() {
                deferred.reject(config);
            });
            return deferred.promise;
        }
    };
}).factory('requestCount', function() {
    var count = 0;
    return {
        increase: function() {
            count++;
        },
        descrease: function() {
            if (count === 0) return;
            count--;
        },
        get: function() {
            return count;
        }
    };
})

Solution 21 - Angularjs

Since the functionality of position:fixed changed recently, I had difficulty showing the gif loader above all elements, so I had to use angular's inbuilt jQuery.

Html

<div ng-controller="FetchController">
	  <div id="spinner"></div>
</div>

Css

#spinner {display: none}
body.spinnerOn #spinner { /* body tag not necessary actually */
   display: block;
   height: 100%;
   width: 100%;
   background: rgba(207, 13, 48, 0.72) url(img/loader.gif) center center no-repeat;
   position: fixed;
   top: 0;
   left: 0;
   z-index: 9999;
}
body.spinnerOn main.content { position: static;} /* and whatever content needs to be moved below your fixed loader div */

Controller

app.controller('FetchController', ['$scope', '$http', '$templateCache', '$location', '$q',
function($scope, $http, $templateCache, $location, $q) {

angular.element('body').addClass('spinnerOn'); // add Class to body to show spinner

$http.post( // or .get(
    // your data here
})
.then(function (response) {
    console.info('success');     
    angular.element('body').removeClass('spinnerOn'); // hide spinner

    return response.data;               
}, function (response) {				   
    console.info('error'); 
    angular.element('body').removeClass('spinnerOn'); // hide spinner
});

})

Hope this helps :)

Solution 22 - Angularjs

All answers are or to complicated, or need to set some variables on every request which is very wrong practice if we know the DRY concept. Here simple interceptor example, I set mouse on wait when ajax starts and set it to auto when ajax ends.

$httpProvider.interceptors.push(function($document) {
    return {
     'request': function(config) {
         // here ajax start
         // here we can for example add some class or show somethin
         $document.find("body").css("cursor","wait");
         
         return config;
      },

      'response': function(response) {
         // here ajax ends
         //here we should remove classes added on request start
         
         $document.find("body").css("cursor","auto");
         
         return response;
      }
    };
  });

Code has to be added in application config app.config. I showed how to change mouse on loading state but in there it is possible to show/hide any loader content, or add, remove some css classes which are showing the loader.

Interceptor will run on every ajax call, so no need to create special boolean variables ( $scope.loading=true/false etc. ) on every http call.

Solution 23 - Angularjs

Here is my implementation, as simple as a ng-show and a request counter.

It use a new service for all request to $http:

myApp.service('RqstSrv', [ '$http', '$rootScope', function($http, $rootScope) {
	var rqstService = {};

	rqstService.call = function(conf) {

        $rootScope.currentCalls = !isNaN($rootScope.currentCalls) ?  $rootScope.currentCalls++ : 0;
		
		$http(conf).then(function APICallSucceed(response) {
			// Handle success
		}, function APICallError(response) {
			// Handle error
		}).then(function() {
			$rootScope.currentCalls--;
		});
	}
} ]);

And then you can use your loader base on the number of current calls:

<img data-ng-show="currentCalls > 0" src="images/ajax-loader.gif"/>

		

Solution 24 - Angularjs

if you want to show loader for every http request call then you can use angular interceptor to manage http request calls ,

here is a sample code

<body data-ng-app="myApp">
<div class="loader">
    <div id="loader"></div>
</div>

<script>
    var app = angular.module("myApp", []);

    app.factory('httpRequestInterceptor', ['$rootScope', '$location', function ($rootScope, $location) {
        return {
            request: function ($config) {
                $('.loader').show();
                return $config;
            },
            response: function ($config) {
                $('.loader').hide();
                return $config;
            },
            responseError: function (response) {
                return response;
            }
        };
    }]);

    app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider',
        function ($stateProvider, $urlRouterProvider, $httpProvider) {
            $httpProvider.interceptors.push('httpRequestInterceptor');
        }]);

</script>
</body>

Solution 25 - Angularjs

Just use ng-show and a boolean

No need to use a directive, no need to get complicated.

Here is the code to put next to submit button or wherever you want the spinner to be:

<span ng-show="dataIsLoading">
  <img src="http://www.nasa.gov/multimedia/videogallery/ajax-loader.gif" style="height:20px;"/>
</span>

And then in your controller:

$scope.dataIsLoading = true

let url = '/whatever_Your_URL_Is'
$http.get(url)
.then(function(response) {
  $scope.dataIsLoading = false
})

Solution 26 - Angularjs

Adding onto @Adam's answer,

Use ng-show as suggested, however, in your case you want the functionality to have multiple requests and await all of them before the loader is hidden.

<span ng-show="pendingRequests > 0">
    <img src="http://www.nasa.gov/multimedia/videogallery/ajax-loader.gif" style="height:20px;"/>
</span>

And then in your controller:

$scope.pendingRequests++;

let url = '/whatever_Your_URL_Is'
$http.get(url)
  .then(function(response) {
      $scope.pendingRequests--;
})

Solution 27 - Angularjs

Here is my solution which i feel is alot easer that the other posted here. Not sure how "pretty" it is though, but it solved all my issues

I have a css style called "loading"

.loading { display: none; }

The html for the loading div can be whatever but I used some FontAwesome icons and the spin method there:

<div style="text-align:center" ng-class="{ 'loading': !loading }">
    <br />
    <h1><i class="fa fa-refresh fa-spin"></i> Loading data</h1>
</div>

On the elements that you want to hide you simply write this:

<something ng-class="{ 'loading': loading }" class="loading"></something>

and in the function i just set this on load.

(function (angular) {
    function MainController($scope) {
        $scope.loading = true

I am using SignalR so in the hubProxy.client.allLocks function (when its done going through the locks) I juts put

 $scope.loading = false
 $scope.$apply();

This also hides the {{someField}} when the page is loading since I am setting the loading class on load and AngularJS removes it afterwards.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAjay BeniwalView Question on Stackoverflow
Solution 1 - AngularjsJosh David MillerView Answer on Stackoverflow
Solution 2 - AngularjsbulltoriousView Answer on Stackoverflow
Solution 3 - AngularjspunkrockpollyView Answer on Stackoverflow
Solution 4 - AngularjsAlexander SweeneyView Answer on Stackoverflow
Solution 5 - AngularjseddiecView Answer on Stackoverflow
Solution 6 - AngularjsPreviewView Answer on Stackoverflow
Solution 7 - AngularjsArnold.KruminsView Answer on Stackoverflow
Solution 8 - AngularjsdrzausView Answer on Stackoverflow
Solution 9 - Angularjsashish malgawaView Answer on Stackoverflow
Solution 10 - Angularjscabaji99View Answer on Stackoverflow
Solution 11 - AngularjsqwwqwwqView Answer on Stackoverflow
Solution 12 - AngularjsOm Prakash SharmaView Answer on Stackoverflow
Solution 13 - AngularjsgeorgeawgView Answer on Stackoverflow
Solution 14 - AngularjsdankView Answer on Stackoverflow
Solution 15 - AngularjsDinesh VaitageView Answer on Stackoverflow
Solution 16 - Angularjsuser1853287View Answer on Stackoverflow
Solution 17 - AngularjsOleg OzimokView Answer on Stackoverflow
Solution 18 - AngularjsChrillewoodzView Answer on Stackoverflow
Solution 19 - AngularjsAnduritView Answer on Stackoverflow
Solution 20 - AngularjsYerkenView Answer on Stackoverflow
Solution 21 - AngularjsMagor MenessyView Answer on Stackoverflow
Solution 22 - AngularjsMaciej SikoraView Answer on Stackoverflow
Solution 23 - AngularjsBancarel ValentinView Answer on Stackoverflow
Solution 24 - AngularjsOm Prakash SharmaView Answer on Stackoverflow
Solution 25 - AngularjsAdamView Answer on Stackoverflow
Solution 26 - AngularjsClayton CView Answer on Stackoverflow
Solution 27 - AngularjsstibayView Answer on Stackoverflow