Angularjs在ajax请求上加载屏幕

Bad*_*ane 116 angularjs angularjs-directive

使用Angularjs,我需要显示一个加载屏幕(一个简单的微调器),直到ajax请求完成.请使用代码段建议任何想法.

Dav*_*Lin 208

而不是设置范围变量来指示数据加载状态,最好让指令为您完成所有事情:

angular.module('directive.loading', [])

    .directive('loading',   ['$http' ,function ($http)
    {
        return {
            restrict: 'A',
            link: function (scope, elm, attrs)
            {
                scope.isLoading = function () {
                    return $http.pendingRequests.length > 0;
                };

                scope.$watch(scope.isLoading, function (v)
                {
                    if(v){
                        elm.show();
                    }else{
                        elm.hide();
                    }
                });
            }
        };

    }]);
Run Code Online (Sandbox Code Playgroud)

使用此指令,您需要做的就是为任何加载动画元素提供"加载"属性:

<div class="loading-spiner-holder" data-loading ><div class="loading-spiner"><img src="..." /></div></div>
Run Code Online (Sandbox Code Playgroud)

您可以在页面上有多个加载微调器.在哪里以及如何布置这些旋转器取决于您,指令将自动为您打开/关闭它.

  • 如果你得到"elm.show()不是函数"错误,你必须在加载角度之前添加jquery. (7认同)
  • 如果我需要异步怎么办?加载多个不同的区域? (3认同)

jzm*_*jzm 55

这是一个例子.它使用简单的ng-show方法和bool.

HTML

<div ng-show="loading" class="loading"><img src="...">LOADING...</div>
<div ng-repeat="car in cars">
  <li>{{car.name}}</li>
</div>
<button ng-click="clickMe()" class="btn btn-primary">CLICK ME</button>
Run Code Online (Sandbox Code Playgroud)

ANGULARJS

  $scope.clickMe = function() {
    $scope.loading = true;
    $http.get('test.json')
      .success(function(data) {
        $scope.cars = data[0].cars;
        $scope.loading = false;
    });
  }
Run Code Online (Sandbox Code Playgroud)

当然你可以将加载框html代码移动到一个指令中,然后在$ scope.loading上使用$ watch.在这种情况下:

HTML:

<loading></loading>
Run Code Online (Sandbox Code Playgroud)

ANGULARJS指令:

  .directive('loading', function () {
      return {
        restrict: 'E',
        replace:true,
        template: '<div class="loading"><img src="..."/>LOADING...</div>',
        link: function (scope, element, attr) {
              scope.$watch('loading', function (val) {
                  if (val)
                      $(element).show();
                  else
                      $(element).hide();
              });
        }
      }
  })
Run Code Online (Sandbox Code Playgroud)

PLUNK:http://plnkr.co/edit/AI1z21?p = preview

  • 感谢分享指令示例 - 很高兴有一个通用的方法答案:) (3认同)

Nej*_*ian 20

我使用ngProgress.

在HTML中包含脚本/ css文件后,将"ngProgress"添加到依赖项中.一旦你这样做,你可以设置这样的东西,这将在检测到路线变化时触发.

angular.module('app').run(function($rootScope, ngProgress) {
  $rootScope.$on('$routeChangeStart', function(ev,data) {
    ngProgress.start();
  });
  $rootScope.$on('$routeChangeSuccess', function(ev,data) {
    ngProgress.complete();
  });
});
Run Code Online (Sandbox Code Playgroud)

对于AJAX请求,您可以执行以下操作:

$scope.getLatest = function () {
    ngProgress.start();

    $http.get('/latest-goodies')
         .success(function(data,status) {
             $scope.latest = data;
             ngProgress.complete();
         })
         .error(function(data,status) {
             ngProgress.complete();
         });
};
Run Code Online (Sandbox Code Playgroud)

只需记住在执行此操作之前将"ngProgress"添加到控制器依赖项中.如果您正在执行多个AJAX请求,请在主应用范围内使用增量变量,以便在调用'ngProgress.complete();'之前跟踪AJAX请求何时完成.


Mah*_* K. 13

使用pendingRequests不正确,因为如Angular文档中所述,此属性主要用于调试目的.

我建议使用拦截器来知道是否有任何活动的异步调用.

module.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.interceptors.push(function ($q, $rootScope) {
        if ($rootScope.activeCalls == undefined) {
            $rootScope.activeCalls = 0;
        }

        return {
            request: function (config) {
                $rootScope.activeCalls += 1;
                return config;
            },
            requestError: function (rejection) {
                $rootScope.activeCalls -= 1;
                return rejection;
            },
            response: function (response) {
                $rootScope.activeCalls -= 1;
                return response;
            },
            responseError: function (rejection) {
                $rootScope.activeCalls -= 1;
                return rejection;
            }
        };
    });
}]);
Run Code Online (Sandbox Code Playgroud)

然后通过$ watch检查指令中的activeCalls是否为零.

module.directive('loadingSpinner', function ($http) {
    return {
        restrict: 'A',
        replace: true,
        template: '<div class="loader unixloader" data-initialize="loader" data-delay="500"></div>',
        link: function (scope, element, attrs) {

            scope.$watch('activeCalls', function (newVal, oldVal) {
                if (newVal == 0) {
                    $(element).hide();
                }
                else {
                    $(element).show();
                }
            });
        }
    };
});
Run Code Online (Sandbox Code Playgroud)


小智 6

执行此操作的最佳方法是使用响应拦截器和自定义指令.使用$ rootScope.$ broadcast&$ rootScope.$ on方法,可以使用pub/sub机制进一步改进该过程.

由于整篇过程记录在一篇写得很好的博客文章中,我不打算再重复一遍.请参阅该文章以提出您所需的实施方案.