trying to add loading wheel using angular when i make ajax call?

后端 未结 4 1004
小鲜肉
小鲜肉 2021-01-26 03:03

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 neith

相关标签:
4条回答
  • 2021-01-26 03:51

    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>
    
    0 讨论(0)
  • 2021-01-26 03:53

    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"/>
    <content ng-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.

    0 讨论(0)
  • 2021-01-26 03:57

    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

    <div class="loading-icon-container" loading>
        <div class="loading-icon">
            <img src="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'];
    
    function MyController($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'];
    
    function loading($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'];
    
    function serviceFactory($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;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
    
    <div ng-app="myApp" ng-controller="MyController">
      <button ng-click="serviceCall()">Servie call</button>
      <!-- loading icon -->
      <div class="loading-icon-container" loading>
        <div class="loading-icon"><img src="https://i.stack.imgur.com/oQ0tF.gif" width="28px" height="28px" alt="Loading..." />
        </div>
      </div>
      <!--<div ng-bind="responseText|json">
      </div>-->
    
    </div>

    0 讨论(0)
  • 2021-01-26 04:02

    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:

    <div ng-controller="thing">
       <img src="http://placehold.it/150" alt="" ng-show="{{isShowing}}"/>
    </div> 
    
    0 讨论(0)
提交回复
热议问题