Skip to content Skip to sidebar Skip to footer

Trying To Add Loading Wheel Using Angular When I Make Ajax Call?

I am trying to implement loading wheel directive when we make ajax call so during the response time i want to display loading wheen, With below code i do not see any error neither

Solution 1:

Instead of showing/hiding for each service call explicitly, you can use a directive to track the ajax request and show/hide the loading symbol at one place.

Below is the similar implementation

Place the loading icon container in index.html

<divclass="loading-icon-container"loading><divclass="loading-icon"><imgsrc="https://i.stack.imgur.com/oQ0tF.gif"width="28px"height="28px"alt="Loading..." /></div></div>

Styling

.loading-icon-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: black;
  z-index: 99999;
  opacity: 0.6;
}

.loading-icon {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 28px;
  height: 28px;
  padding: 5px;
  border: 1px solid black;
}

Implement loading directive

return {
    restrict: 'A',
    link: function(scope, element, attrs) {
        scope.$watch(function() {
            return$http.pendingRequests.length > 0;
        }, function(hasPending) {
            if (hasPending) {
                element[0].style.display = '';
            } else {
                element[0].style.display = 'none';
            }
        });
    }
}

Demo

angular
  .module('myApp', []);

angular
  .module('myApp')
  .controller('MyController', MyController)
  .directive('loading', loading)
  .factory('serviceFactory', serviceFactory);

MyController.$inject = ['$scope', 'serviceFactory'];

functionMyController($scope, serviceFactory) {

  $scope.serviceCall = function() {
    var reqObj = {
      url: 'https://reqres.in/api/users?delay=3/photos',
      method: 'GET'
    }
    serviceFactory
      .serviceCall(reqObj)
      .then(function(data) {
        $scope.responseText = data.data;
        console.log(data);
      });
  };
}

loading.$inject = ['$http'];

functionloading($http) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      scope.$watch(function() {
        return $http.pendingRequests.length > 0;
      }, function(hasPending) {
        if (hasPending) {
          element[0].style.display = '';
        } else {
          element[0].style.display = 'none';
        }
      });
    }
  };
}

serviceFactory.$inject = ['$http'];

functionserviceFactory($http) {
  var obj = {};
  obj.serviceCall = function(reqObj) {
    return $http(reqObj).then(function(success) {
      return success.data;
    });
  };
  return obj;

}
.loading-icon-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: black;
  z-index: 99999;
  opacity: 0.6;
}

.loading-icon {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 28px;
  height: 28px;
  padding: 5px;
  border: 1px solid black;
}
<scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script><divng-app="myApp"ng-controller="MyController"><buttonng-click="serviceCall()">Servie call</button><!-- loading icon --><divclass="loading-icon-container"loading><divclass="loading-icon"><imgsrc="https://i.stack.imgur.com/oQ0tF.gif"width="28px"height="28px"alt="Loading..." /></div></div><!--<div ng-bind="responseText|json">
  </div>--></div>

Solution 2:

In a nutshell, what I would do instead would be to always have the loading wheel in the view, and just use ng-if to control whether it shows or not.

// view
<loading-wheel ng-if="vm.loading"/>
<contentng-if="!vm.loading"/>

And then, whenever you go to load, just set vm.loading (probably this.loading depending on context) to true, and when done, false. Then the loading wheel will show up when it's ready, and go away when it's done.

It's a lot cleaner and easier than manually showing and hiding it.

Solution 3:

Implementing an interceptor for HTTP requests. Inside the interceptor you will fire events that you will be able to listen across the application.

Once it is happening you can use the events inside your main controller(or some directive) to show hide the loader.

MyApp.factory('Global-httpInterceptor', ['$q', '$rootScope', '$log', function ($q, $rootScope, $log) {

    var numLoadings = 0;

    return {
        request: function (config) {

            numLoadings++;
            // Show loader$rootScope.$broadcast("ajax:start", { $config: config });
            return config || $q.when(config);

        },
        response: function (response) {

            if ((--numLoadings) === 0) {
                // Hide loader$rootScope.$broadcast("ajax:finished", { $config: response });
            }
            $rootScope.$broadcast("ajax:success", { $response: response });

            return response || $q.when(response);

        },
        responseError: function (response) {

            if (!(--numLoadings)) {
                // Hide loader$rootScope.$broadcast("ajax:finished", { $response: response });
            }
            $rootScope.$broadcast("ajax:error", { $response: response });
            return$q.reject(response);
        }
    };
}])
.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.interceptors.push('Global-httpInterceptor');
}]);

Example Use

angular.module('App', [])
  .directive('loading', function () {
      return {
        restrict: 'E',
        replace:true,
        template: '<div class="loading"><img src="http://www.nasa.gov/multimedia/videogallery/ajax-loader.gif" width="20" height="20" />LOADING...</div>',
        link: function (scope, element, attr) {
            $rootScope.$on("ajax:start", function () {
                element.show();
            });
            $rootScope.$on("ajax:finished", function () {
                element.hide()
            });
        }
      }
  })

And at the view remains the same

<loading></loading>

Solution 4:

Jeesk. Most of these answers seem like overkill, why not just include the image in your controller view and toggle it with an ng-show or ng-if?

( Please pardon my use of the API or whatever. Obviously the $http request should be abstracted into a service or something. I did this quickly and it's been a bit since I have worked with Angular 1)

angular.module("whatever")
  .controller("thing", function($scope, $http/* and whatever else*/) {


  $scope.isShowing = false;

  $scope.makeAJAXCall = function() {
    $scope.isShowing = true;

    $http.get("whatever.com")
      .success(function() {
      $scope.isShowing = false;
    });

  }
});

And the HTML:

<divng-controller="thing"><imgsrc="http://placehold.it/150"alt=""ng-show="{{isShowing}}"/></div>

Post a Comment for "Trying To Add Loading Wheel Using Angular When I Make Ajax Call?"