我正在使用AngularJS的$http服务来进行Ajax请求。
如何在Ajax请求执行时显示旋转GIF(或另一种类型的忙碌指示器)?
我在AngularJS文档中没有看到类似ajaxstartevent的东西。
我正在使用AngularJS的$http服务来进行Ajax请求。
如何在Ajax请求执行时显示旋转GIF(或另一种类型的忙碌指示器)?
我在AngularJS文档中没有看到类似ajaxstartevent的东西。
当前回答
下面是AngularJS当前使用的咒语:
angular.module('SharedServices', [])
.config(function ($httpProvider) {
$httpProvider.responseInterceptors.push('myHttpInterceptor');
var spinnerFunction = function (data, headersGetter) {
// todo start the spinner here
//alert('start spinner');
$('#mydiv').show();
return data;
};
$httpProvider.defaults.transformRequest.push(spinnerFunction);
})
// register the interceptor as a service, intercepts ALL angular ajax http calls
.factory('myHttpInterceptor', function ($q, $window) {
return function (promise) {
return promise.then(function (response) {
// do something on success
// todo hide the spinner
//alert('stop spinner');
$('#mydiv').hide();
return response;
}, function (response) {
// do something on error
// todo hide the spinner
//alert('stop spinner');
$('#mydiv').hide();
return $q.reject(response);
});
};
});
//regular angular initialization continued below....
angular.module('myApp', [ 'myApp.directives', 'SharedServices']).
//.......
这里是它的其余部分(HTML / CSS)....使用
$('#mydiv').show();
$('#mydiv').hide();
来切换它。注意:以上是在post开头的angular模块中使用的
#mydiv {
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
z-index:1000;
background-color:grey;
opacity: .8;
}
.ajax-loader {
position: absolute;
left: 50%;
top: 50%;
margin-left: -32px; /* -1 * image width / 2 */
margin-top: -32px; /* -1 * image height / 2 */
display: block;
}
<div id="mydiv">
<img src="lib/jQuery/images/ajax-loader.gif" class="ajax-loader"/>
</div>
其他回答
如果你想为每个HTTP请求调用显示加载器,那么你可以使用angular interceptor来管理HTTP请求调用。
下面是一个示例代码
<body data-ng-app="myApp">
<div class="loader">
<div id="loader"></div>
</div>
<script>
var app = angular.module("myApp", []);
app.factory('httpRequestInterceptor', ['$rootScope', '$location', function ($rootScope, $location) {
return {
request: function ($config) {
$('.loader').show();
return $config;
},
response: function ($config) {
$('.loader').hide();
return $config;
},
responseError: function (response) {
return response;
}
};
}]);
app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider',
function ($stateProvider, $urlRouterProvider, $httpProvider) {
$httpProvider.interceptors.push('httpRequestInterceptor');
}]);
</script>
</body>
这是我的解决方案,我觉得比其他贴在这里的要容易得多。虽然不知道它有多“漂亮”,但它解决了我所有的问题
我有一个css样式叫做loading
.loading { display: none; }
加载div的html可以是任何东西,但我使用了一些FontAwesome图标和旋转方法:
<div style="text-align:center" ng-class="{ 'loading': !loading }">
<br />
<h1><i class="fa fa-refresh fa-spin"></i> Loading data</h1>
</div>
在你想要隐藏的元素上,你只需这样写:
<something ng-class="{ 'loading': loading }" class="loading"></something>
在函数中,我把这个设为load。
(function (angular) {
function MainController($scope) {
$scope.loading = true
我使用的是SignalR,所以在hubProxy.client.allLocks函数(当它完成了通过锁),我只是把
$scope.loading = false
$scope.$apply();
当页面加载时,这也隐藏了{{someField}},因为我在load上设置了加载类,AngularJS随后删除了它。
下面是一个使用指令和ng-hide的版本。
这将显示所有通过angular的$http服务调用的加载器。
在模板中:
<div class="装载机" </div>
指令:
angular.module('app')
.directive('loading', ['$http', function ($http) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.isLoading = function () {
return $http.pendingRequests.length > 0;
};
scope.$watch(scope.isLoading, function (value) {
if (value) {
element.removeClass('ng-hide');
} else {
element.addClass('ng-hide');
}
});
}
};
}]);
通过在元素上使用ng-hide类,可以避免使用jquery。
自定义:添加拦截器
如果你创建了一个加载拦截器,你可以根据条件显示/隐藏加载器。
指令:
var loadingDirective = function ($rootScope) {
return function ($scope, element, attrs) {
$scope.$on("loader_show", function () {
return element.removeClass('ng-hide');
});
return $scope.$on("loader_hide", function () {
return element.addClass('ng-hide');
});
};
};
拦截器:
例如:当响应时不显示旋转器。背景=== true; 拦截请求和/或响应设置$rootScope.$broadcast("loader_show");或rootScope。广播美元(“loader_hide”);
关于编写拦截器的更多信息
这真的取决于你的特定用例,但一个简单的方法是遵循这样的模式:
.controller('MainCtrl', function ( $scope, myService ) {
$scope.loading = true;
myService.get().then( function ( response ) {
$scope.items = response.data;
}, function ( response ) {
// TODO: handle the error somehow
}).finally(function() {
// called no matter success or failure
$scope.loading = false;
});
});
然后在模板中对它做出反应:
<div class="spinner" ng-show="loading"></div>
<div ng-repeat="item in items>{{item.name}}</div>
如果我们知道DRY的概念,那么所有的答案都是复杂的,或者需要在每个请求上设置一些变量,这是非常错误的做法。这里是一个简单的拦截器的例子,当ajax启动时,我将鼠标设置为等待,当ajax结束时设置为自动。
$httpProvider.interceptors.push(function($document) {
return {
'request': function(config) {
// here ajax start
// here we can for example add some class or show somethin
$document.find("body").css("cursor","wait");
return config;
},
'response': function(response) {
// here ajax ends
//here we should remove classes added on request start
$document.find("body").css("cursor","auto");
return response;
}
};
});
代码必须添加到应用程序配置app.config中。我展示了如何改变鼠标加载状态,但在那里,它是可以显示/隐藏任何加载器内容,或添加,删除一些css类显示加载器。
拦截器将在每次ajax调用上运行,因此不需要创建特殊的布尔变量($scope. js)。加载=true/false等)在每个HTTP调用。