19

I'm new in AngularJS and trying to find the way how to display wait message while data loading? I mean data starts loading, display message and remove it when data loading is done.

I've searched the internet but haven't found anything I need...

1
  • In case you want to show a loading indicator for web service calls, there is also a way to intercept http calls. There are some blog posts on how to implement such an interceptor. A good one is this: codingsmackdown.tv/blog/2013/01/02/… Commented Aug 21, 2013 at 14:18

5 Answers 5

46
<div ng-if="data.dataLoading">
    Loading...
</div>

JS

$scope.data.dataLoading = true;

return someService.getData().then(function (results) {                    
    ...
}).finally(function () {
    $scope.data.dataLoading = false;
});
Sign up to request clarification or add additional context in comments.

3 Comments

This approach fits very well. Thanks.
Problem: it will show the "Loading..." message even if server returned you empty list or null.
if I do this inside ng-click handler, and do this.data.dataLoading = true, it does'nt update the view.
5

Depends from where you're loading the data. One solution I used was to create a LoadingService

app.factory('LoadingService', function($rootScope) {
    return {
        loading : function(message) {
             $rootScope.loadingMessage = message;
        },
        loaded : function() {
             $rootScope.loadingMessage = null;
        }
    }
}).controller('FooController', function($scope,$http,LoadingService) {

   $scope.loadSomeData = function() {
       LoadingService.loading('Data is loading');

       $http.get('/data').finally(function() {
            LoadingService.loaded();
       });
   };
});

Since I had only one place where the message was being displayed I could use RootScope to handle this. If you want to have a loading message multiple times you could write a directive also to handle this like Codezilla posted

Comments

1

Edit: does not work on version 1.3.0 . Use request/response interceptors.

If you want to listen to all requests globally and display a loading widget whenever there's a request pending, you can count the requests using request/response transformers. You simply add a counter and increase on a new request and decrease it on response. I use a provider for that:

$httpProvider
  .defaults
  .transformRequest
  .push(function(data) {
      requestNotificationProvider
      .fireRequestStarted(data);
      return data;
});

And the same for transformResponse. Then the same provider holds the information on how many requests are pending and you can use them in a directive. You can read (& copy/paste the code) a full blog post on that here: http://www.kvetis.com/2014/01/angularjs-loading-widget.html There's a working demo in attached.

Comments

1

I've answered this question in this StackOverflow article, but here's a recap of what I did.

If you style your code correctly, and make sure all calls to a web service pass through one particular factory function, then you can make that factory function handle showing and hiding your "Please Wait" popup.

Here's the factory function which I use to call all of my GET web services:

myApp.factory('httpGetFactory', function ($http, $q) {
    return function (scope, URL) {
        //  This Factory method calls a GET web service, and displays a modal error message if something goes wrong.
        scope.$broadcast('app-start-loading');          //  Show the "Please wait" popup

        return $http({
            url: URL,
            method: "GET",
            headers: { 'Content-Type': undefined }
        }).then(function (response) {
            scope.$broadcast('app-finish-loading');     //  Hide the "Please wait" popup
            if (typeof response.data === 'object') {
                return response.data;
            } else {
                // invalid response
                return $q.reject(response.data);
            }
        }, function (errorResponse) {
            scope.$broadcast('app-finish-loading');     //  Hide the "Please wait" popup

            //  The WCF Web Service returned an error.  
            //  Let's display the HTTP Status Code, and any statusText which it returned.
            var HTTPErrorNumber = (errorResponse.status == 500) ? "" : "HTTP status code: " + errorResponse.status + "\r\n";
            var HTTPErrorStatusText = errorResponse.statusText;

            var message = HTTPErrorNumber + HTTPErrorStatusText;

            BootstrapDialog.show({
                title: 'Error',
                message: message,
                buttons: [{
                    label: 'OK',
                    action: function (dialog) {
                        dialog.close();
                    },
                    draggable: true
                }]
            });

            return $q.reject(errorResponse.data);
        });
    };
});

This would get called like this:

myApp.webServicesURL = "http://localhost:15021/Service1.svc";

var dsLoadAllEmployees = function (scope)
{
     //  Load all survey records, from our web server
     $scope.LoadingMessage = "Loading Employees data...";

     var URL = myApp.webServicesURL + "/loadAllEmployees";
     return httpGetFactory(scope, URL);
}

Here's the "Please wait" control which I use on each page..

<please-wait message="{{LoadingMessage}}" ></please-wait>

... and its code looks like this...

myApp.directive('pleaseWait',  
    function ($parse) {
        return {
            restrict: 'E',
            replace: true,
            scope: {
                message: '@message'
            },
            link: function (scope, element, attrs) {
                scope.$on('app-start-loading', function () {
                    element.fadeIn(); 
                });
                scope.$on('app-finish-loading', function(){
                    element.animate({
                        top: "+=15px",
                        opacity: "0"
                    }, 500);
                });
            },
            template: '<div class="cssPleaseWait"><span>{{ message }}</span></div>'
        }
    });

Using this structure, any of my Angular controllers can load data from a web service in just a few lines, and leave the factory to look after showing/hiding the "Please wait" message and to display any errors which occur:

   $scope.LoadAllSurveys = function () {
        DataService.dsLoadAllSurveys($scope).then(function (response) {
            //  Success
            $scope.listOfSurveys = response.GetAllSurveysResult;
        });
   }

Nice, hey ?

Comments

0

I dont know if is the correct way, but I put on my template

 <img id="spinner" ng-src="images/spinner.gif" ng-if="!data" >
 <div ng-repeat="repo in repos | orderBy: repoSortOrder">...</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.