我正在使用AngularJS的$http
服务进行Ajax请求。
在执行Ajax请求时,如何显示旋转GIF(或其他类型的忙指示器)?
我在AngularJS文档中没有看到类似于ajaxstartevent
的东西。
我正在使用AngularJS的$http
服务进行Ajax请求。
在执行Ajax请求时,如何显示旋转GIF(或其他类型的忙指示器)?
我在AngularJS文档中没有看到类似于ajaxstartevent
的东西。
.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>
$scope.loading = 0;
,当请求开始时,执行$scope.loading ++;
,当请求结束时,执行$scope.loading--;
。在模板中没有任何需要更改的内容。 因此,当至少存在一个正在进行的请求时,会显示旋转器,否则会隐藏。 - JMaylin$scope.loading = false
,而是将它放在 .finally()
中。代码如下所示:mySvc.get().then(success, fail).finally(function() { $scope.loading = false; });
- Tom以下是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();
切换它。注意:上述内容用于文章开头的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>
angular.element('#mydiv').show()
而不是 $('#mydiv').show()
。该语句意为:在代码中显示 id 为“mydiv”的元素,前者使用了 Angular 的 element
方法来获取 DOM 元素,后者使用了 jQuery 库的 $
符号来完成相同的操作。 - JMaylinng-class
指令来代替使用 JQuery 显示和隐藏元素吗? - James Heald以下是使用directive
和ng-hide
的版本。
这将在通过Angular的$http
服务进行所有调用时显示加载器。
在模板中:
<div class="loader" data-loading></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');
});
};
};
拦截器:
response.background === true;
时不显示spinner
;request
和/或response
以设置$rootScope.$broadcast("loader_show");
或$rootScope.$broadcast("loader_hide");
。$http
иї›иЎЊи°ѓз”Ёж—¶пјЊе®ѓйѓЅдјљи‡ЄеЉЁиїђиЎЊгЂ‚ - punkrockpolly如果您正在使用ngResource,对象的$resolved属性对于加载器非常有用:
对于以下资源:
var User = $resource('/user/:id', {id:'@id'});
var user = User.get({id: 1})
您可以将加载器链接到资源对象的 $resolved 属性:<div ng-hide="user.$resolved">Loading ...</div>
https://github.com/wongatech/angular-http-loader 是一个不错的项目。
这里有一个示例 http://wongatech.github.io/angular-http-loader/
下面的代码展示了请求发生时的模板示例/loader.tpl.html。
<div ng-http-loader template="example/loader.tpl.html"></div>
我刚刚发现了angular-busy
指令,它会根据某些异步调用显示一个小的加载器。
例如,如果你需要发起一个GET
请求,在你的$scope
中引用这个promise对象,
$scope.req = $http.get('http://google.fr');
<div cg-busy="req"></div>
这里是GitHub链接。
您还可以使用bower
进行安装(不要忘记更新项目依赖):
bower install angular-busy --save
如果您正在服务/工厂中包装api调用,则可以在那里跟踪加载计数器(根据答案和@JMaylin的出色同时建议),并通过指令引用加载计数器,或任何组合。
yourModule
.factory('yourApi', ['$http', function ($http) {
var api = {}
//#region ------------ spinner -------------
// ajax loading counter
api._loading = 0;
/**
* Toggle check
*/
api.isOn = function () { return api._loading > 0; }
/**
* Based on a configuration setting to ignore the loading spinner, update the loading counter
* (for multiple ajax calls at one time)
*/
api.spinner = function(delta, config) {
// if we haven't been told to ignore the spinner, change the loading counter
// so we can show/hide the spinner
if (NG.isUndefined(config.spin) || config.spin) api._loading += delta;
// don't let runaway triggers break stuff...
if (api._loading < 0) api._loading = 0;
console.log('spinner:', api._loading, delta);
}
/**
* Track an ajax load begin, if not specifically disallowed by request configuration
*/
api.loadBegin = function(config) {
api.spinner(1, config);
}
/**
* Track an ajax load end, if not specifically disallowed by request configuration
*/
api.loadEnd = function (config) {
api.spinner(-1, config);
}
//#endregion ------------ spinner -------------
var baseConfig = {
method: 'post'
// don't need to declare `spin` here
}
/**
* $http wrapper to standardize all api calls
* @param args stuff sent to request
* @param config $http configuration, such as url, methods, etc
*/
var callWrapper = function(args, config) {
var p = angular.extend(baseConfig, config); // override defaults
// fix for 'get' vs 'post' param attachment
if (!angular.isUndefined(args)) p[p.method == 'get' ? 'params' : 'data'] = args;
// trigger the spinner
api.loadBegin(p);
// make the call, and turn of the spinner on completion
// note: may want to use `then`/`catch` instead since `finally` has delayed completion if down-chain returns more promises
return $http(p)['finally'](function(response) {
api.loadEnd(response.config);
return response;
});
}
api.DoSomething = function(args) {
// yes spinner
return callWrapper(args, { cache: true });
}
api.DoSomethingInBackground = function(args) {
// no spinner
return callWrapper(args, { cache: true, spin: false });
}
// expose
return api;
});
(function (NG) {
var loaderTemplate = '<div class="ui active dimmer" data-ng-show="hasSpinner()"><div class="ui large loader"></div></div>';
/**
* Show/Hide spinner with ajax
*/
function spinnerDirective($compile, api) {
return {
restrict: 'EA',
link: function (scope, element) {
// listen for api trigger
scope.hasSpinner = api.isOn;
// attach spinner html
var spin = NG.element(loaderTemplate);
$compile(spin)(scope); // bind+parse
element.append(spin);
}
}
}
NG.module('yourModule')
.directive('yourApiSpinner', ['$compile', 'yourApi', spinnerDirective]);
})(angular);
<div ng-controller="myCtrl" your-api-spinner> ... </div>
对于页面加载和模态框,最简单的方法是使用ng-show
指令,并使用其中一个作用域数据变量。例如:
ng-show="angular.isUndefined(scope.data.someObject)".
这里,当someObject
未定义时,旋转图标将显示。一旦服务返回数据并填充了someObject
,旋转图标将返回到隐藏状态。
Based on Josh David Miller response:
<body>
<header>
</header>
<div class="spinner" ng-show="loading">
<div class="loader" ></div>
</div>
<div ng-view=""></div>
<footer>
</footer>
</body>
添加这个CSS:
.loader {
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid #3498db;
border-bottom : 16px solid black;
width: 80px;
height: 80px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
position: absolute;
top: 45%;
left: 45%;
}
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.spinner{
width: 100%;
height: 100%;
z-index: 10000;
position: absolute;
top: 0;
left: 0;
margin: 0 auto;
text-align: center;
vertical-align: middle;
background: white;
opacity: 0.6;
}
在你的Angular中添加以下内容:
$rootScope.loading = false; 当 $http.get 结束时,$rootScope.loading = true;
这应该是添加Spinner的最简单方法:
您可以使用ng-show及任何一个美丽的Spinner的div标签 http://tobiasahlin.com/spinkit/ {{这不是我的页面}}
然后,您可以使用以下逻辑:
//ajax start
$scope.finderloader=true;
$http({
method :"POST",
url : "your URL",
data: { //your data
}
}).then(function mySucces(response) {
$scope.finderloader=false;
$scope.search=false;
$scope.myData =response.data.records;
});
//ajax end
<div ng-show="finderloader" class=spinner></div>
//add this in your HTML at right place