【问题标题】:trying to add loading wheel using angular when i make ajax call?当我进行ajax调用时尝试使用角度添加加载轮?
【发布时间】:2017-03-09 16:30:49
【问题描述】:

当我们进行 ajax 调用时,我正在尝试实现加载轮指令,因此在响应时间我想显示加载时,使用下面的代码我没有看到任何错误,加载轮也没有。

有没有更好的方法来使用 angularJs 实现加载轮?

下面的代码有什么错误?

main.html

<loading></loading>

<ul style="list-style: none;">
    <li ng-repeat="message in event | limitTo:1000" ng-class="{lastItem: $last}"><span>{{message.value}}</span></li>
</ul>

加载.js

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) {
              scope.$watch('loading', function (val) {
                  if (val)
                      $(element).show();
                  else
                      $(element).hide();
              });
        }
      }
  })

ctrl.js

$scope.searchServerFile = function() {
        console.log($scope.vm.search);
        if ($scope.vm.search === undefined || $scope.vm.search === null) {
            toastr.warning('A search keyword must only contain a-z, A-Z, 0-9, or space characters.');
        } else {
            $scope.loading = true;
            searchFactory.getServerSearch($scope.vm.search, searchEnv).then(function(response) {
                    $scope.modalInstance.rendered.then(function() {
                        $rootScope.$broadcast('displaySearchResults', {
                            messageObj: response.data

                        });
                        $scope.loading = false;
                    });
                }
        }

【问题讨论】:

标签: javascript angularjs angularjs-directive


【解决方案1】:

您可以使用指令来跟踪 ajax 请求并在一个地方显示/隐藏加载符号,而不是显式地显示/隐藏每个服务调用。

下面是类似的实现

将加载图标容器放在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>

样式

.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;
}

实现loading 指令

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';
            }
        });
    }
}

演示

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>

【讨论】:

  • 在我的情况下,我在控制器中调用工厂,是否可以将这种情况与您的逻辑一起使用
  • 我只是在控制器中使用$http 进行演示。理想情况下,您应该使用工厂来获取数据。 是的。无论您是在控制器中调用还是使用工厂,只要有待处理的 AJAX 调用,它就会起作用
  • 那么在工厂的情况下我将如何使用loading()函数?
  • 我没有在你的代码中看到你是如何使用loading 指令的,你把所有东西都混合在一个文件中,比如控制器、工厂和指令。你能给我单独使用工厂指令的例子吗?我对指令相当陌生,
  • @hussain 我能理解你是Directives 的新手。我在文件中给出了工作示例,因为堆栈 sn-ps 不允许创建多个文件。
【解决方案2】:

简而言之,我要做的就是始终在视图中显示加载轮,并使用ng-if 来控制它是否显示。

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

然后,无论何时加载,只需将vm.loading(可能是this.loading,取决于上下文)设置为true,完成后设置为false。然后加载轮在准备好时会出现,完成后会消失。

它比手动显示和隐藏它更干净、更容易。

【讨论】:

    【解决方案3】:

    为 HTTP 请求实现 拦截器。 在拦截器中,您将触发可以在整个应用程序中侦听的事件。

    一旦发生,您可以使用主控制器(或某些指令)中的事件来显示隐藏加载器。

    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');
    }]);
    

    示例使用

    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()
                });
            }
          }
      })
    

    在视图上保持不变

    <loading></loading>
    

    【讨论】:

    • 你能给我一个例子,我将如何从控制器和视图中使用这个。
    • 是的,刚刚添加
    • http请求时需要在控制器中设置布尔值吗?
    • 没有。只需在加载器 html 代码中添加“加载器”指令,它就会自动显示/隐藏
    • 在您的情况下,您可以只监听“加载”指令中的事件,而不是在我的示例中创建事件
    【解决方案4】:

    天哪。这些答案中的大多数看起来都有些矫枉过正,为什么不将图像包含在您的controller 视图中并用ng-showng-if 切换它?

    (请原谅我使用 API 或其他任何东西。显然,$http 请求应该被抽象为服务或其他东西。我很快就做到了,自从我使用 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;
        });
    
      }
    });
    

    还有 HTML:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-29
      • 2021-01-01
      相关资源
      最近更新 更多