You wish to display a loading spinner while waiting for an AJAX request to be finished.
We will use the Twitter search API for our example to render a list of search results. When pressing the button the AJAX request is run and the spinner image should be shown until the request is done.
<body ng-app="MyApp" ng-controller="MyCtrl">
<div>
<button class="btn" ng-click="load()">Load Tweets</button>
<img id="spinner" ng-src="img/spinner.gif" style="display:none;">
</div>
<div>
<ul ng-repeat="tweet in tweets">
<li>
<img ng-src="{{tweet.profile_image_url}}" alt="">
{{tweet.from_user}}
{{tweet.text}}
</li>
</ul>
</div>
</body>
An Angular.js interceptor for all AJAX calls is used, which allows you to execute code before the actual request is started and when it is finished.
var app = angular.module("MyApp", ["ngResource"]);
app.config(function ($httpProvider) {
$httpProvider.responseInterceptors.push('myHttpInterceptor');
var spinnerFunction = function spinnerFunction(data, headersGetter) {
$("#spinner").show();
return data;
};
$httpProvider.defaults.transformRequest.push(spinnerFunction);
});
app.factory('myHttpInterceptor', function ($q, $window) {
return function (promise) {
return promise.then(function (response) {
$("#spinner").hide();
return response;
}, function (response) {
$("#spinner").hide();
return $q.reject(response);
});
};
});
Note that we use jQuery to show the spinner in the configuration step and hide the spinner in the interceptor.
Additionally we use a controller to handle the button click and execute the search request.
app.controller("MyCtrl", function($scope, $resource, $rootScope) {
$scope.resultsPerPage = 5;
$scope.page = 1;
$scope.searchTerm = "angularjs";
$scope.twitter = $resource('http://search.twitter.com/search.json',
{ callback:'JSON_CALLBACK',
page: $scope.page,
rpp: $scope.resultsPerPage,
q: $scope.searchTerm },
{ get: { method:'JSONP' } });
$scope.load = function() {
$scope.twitter.get(function(data) {
$scope.tweets = data.results;
});
};
});
Don’t forget to add ngResource
to the module and load it via script tag.
You can find the complete example on github.
The template is the easy part of this recipe since it renders a list of tweets using the ng-repeat
directive. Let us jump straight to the interceptor code.
The interceptor is implemented using the factory method and attaches itself to the promise function of the AJAX response to hide the spinner on success or failure. Note that on failure we use the reject
function of the $q service, Angular’s promise/deferred implementation.
Now, in the config
method we add our inceptor to the list of responseInterceptors of $httpProvider
to register it properly. In a similar manner we add the spinnerFunction
to the default transformRequest
list in order to call it before each AJAX request.
The controller is responsible for using a $resource
object and handling the button click with the load
function. We are using JSONP here to allow this code to be executed locally even though it is served by a different domain.