ฉันใช้$http
บริการของ AngularJS เพื่อทำการร้องขอ Ajax
GIF สปินเนอร์จะแสดงได้อย่างไร (หรือตัวบ่งชี้ไม่ว่างประเภทอื่น) ในขณะที่คำขอ Ajax กำลังทำงาน
ฉันไม่เห็นสิ่งที่ต้องการajaxstartevent
ในเอกสารประกอบของ AngularJS
ฉันใช้$http
บริการของ AngularJS เพื่อทำการร้องขอ Ajax
GIF สปินเนอร์จะแสดงได้อย่างไร (หรือตัวบ่งชี้ไม่ว่างประเภทอื่น) ในขณะที่คำขอ Ajax กำลังทำงาน
ฉันไม่เห็นสิ่งที่ต้องการajaxstartevent
ในเอกสารประกอบของ AngularJS
คำตอบ:
นี่คือคาถา 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();
เพื่อสลับ หมายเหตุ: ข้างต้นจะใช้ในโมดูลเชิงมุมที่จุดเริ่มต้นของการโพสต์
#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()
ng-class
คำสั่งแทนที่จะใช้ JQuery เพื่อแสดงและซ่อนองค์ประกอบ?
สิ่งนี้ขึ้นอยู่กับกรณีการใช้งานเฉพาะของคุณ แต่วิธีการง่าย ๆ จะเป็นไปตามรูปแบบดังนี้:
.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>
loading
เป็นจำนวนเต็ม$scope.loading = 0;
เมื่อคำขอเริ่มต้นที่คุณทำและเมื่อมันจบลงที่คุณทำ$scope.loading++;
$scope.loading--;
และไม่มีอะไรเปลี่ยนแปลงในเทมเพลต ดังนั้นสปินเนอร์จะปรากฏขึ้นเมื่อมีการร้องขออย่างน้อยหนึ่งความคืบหน้าและซ่อนเวลาที่เหลืออยู่
$scope.loading = false
.finally()
มันจะมีลักษณะดังนี้:mySvc.get().then(success, fail).finally(function() { $scope.loading = false; });
ต่อไปนี้เป็นรุ่นที่ใช้และdirective
ng-hide
นี่จะแสดงตัวโหลดระหว่างการโทรทั้งหมดผ่าน$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
ปรับแต่ง: เพิ่ม interceptor
หากคุณสร้างตัวโหลดการโหลดคุณสามารถแสดง / ซ่อนตัวโหลดตามเงื่อนไข
สั่ง:
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');
});
};
};
interceptor:
spinner
เมื่อใดresponse.background === true;
request
และ / หรือresponse
เพื่อตั้งค่า$rootScope.$broadcast("loader_show");
หรือ$rootScope.$broadcast("loader_hide");
$http
บริการใด ๆ
หากคุณใช้ ngResource แอตทริบิวต์ $ ที่แก้ไขแล้วของวัตถุจะเป็นประโยชน์สำหรับโหลดเดอร์:
สำหรับทรัพยากรดังต่อไปนี้:
var User = $resource('/user/:id', {id:'@id'});
var user = User.get({id: 1})
คุณสามารถลิงก์โหลดเดอร์ไปยังแอตทริบิวต์ $ ที่ได้รับการแก้ไขของวัตถุทรัพยากร:
<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
คำสั่งที่แสดงตัวโหลดเล็ก ๆ น้อย ๆ ขึ้นอยู่กับการเรียก async
ตัวอย่างเช่นถ้าคุณมีที่จะทำให้การGET
อ้างอิงสัญญาในของคุณ$scope
,
$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
เติมข้อมูลสปินเนอร์จะกลับสู่สถานะที่ซ่อนอยู่
นี่เป็นวิธีที่ง่ายที่สุดในการเพิ่มเครื่องปั่นด้ายฉันเดา: -
คุณสามารถใช้ ng-show กับแท็ก 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
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;
}
และเพียงเพิ่มมุมของคุณ:
$ rootScope.loading = false; $ rootScope.loading = true; -> เมื่อ $ http.get สิ้นสุดลง
การแชร์คำตอบที่ดีจาก @bulltorious รุ่นของฉันอัปเดตสำหรับการสร้างเชิงมุมที่ใหม่กว่า (ฉันใช้เวอร์ชัน 1.5.8 กับรหัสนี้) และยังรวมแนวคิดของ @ JMaylin ไว้ด้วยการใช้ตัวนับ ตัวเลือกเพื่อข้ามการแสดงภาพเคลื่อนไหวสำหรับคำขอที่ใช้เวลาน้อยกว่าจำนวนมิลลิวินาทีขั้นต่ำ:
var app = angular.module('myApp');
var BUSY_DELAY = 1000; // Will not show loading graphic until 1000ms have passed and we are still waiting for responses.
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('busyHttpInterceptor');
})
.factory('busyHttpInterceptor', ['$q', '$timeout', function ($q, $timeout) {
var counter = 0;
return {
request: function (config) {
counter += 1;
$timeout(
function () {
if (counter !== 0) {
angular.element('#busy-overlay').show();
}
},
BUSY_DELAY);
return config;
},
response: function (response) {
counter -= 1;
if (counter === 0) {
angular.element('#busy-overlay').hide();
}
return response;
},
requestError: function (rejection) {
counter -= 1;
if (counter === 0) {
angular.element('#busy-overlay').hide();
}
return rejection;
},
responseError: function (rejection) {
counter -= 1;
if (counter === 0) {
angular.element('#busy-overlay').hide();
}
return rejection;
}
}
}]);
คุณสามารถใช้ interceptor เชิงมุมเพื่อจัดการการร้องขอ http
<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>
นี่เป็นวิธีที่ง่ายในการแสดงสปินเนอร์ที่ไม่ต้องการไลบรารีของบุคคลที่สามตัวแปลงสัญญาณหรือ jQuery
ในคอนโทรลเลอร์ให้ตั้งค่าและรีเซ็ตแฟล็ก
function starting() {
//ADD SPINNER
vm.starting = true;
$http.get(url)
.then(function onSuccess(response) {
vm.data = response.data;
}).catch(function onReject(errorResponse) {
console.log(errorResponse.status);
}).finally(function() {
//REMOVE SPINNER
vm.starting = false;
});
};
ใน HTML ให้ใช้การตั้งค่าสถานะ:
<div ng-show="vm.starting">
<img ng-src="spinnerURL" />
</div>
<div ng-hide="vm.starting">
<p>{{vm.data}}</p>
</div>
การvm.starting
ตั้งค่าสถานะtrue
เมื่อ XHR เริ่มต้นและล้างข้อมูลเมื่อ XHR เสร็จสมบูรณ์
มันใช้งานได้ดีสำหรับฉัน:
HTML:
<div id="loader" class="ng-hide" ng-show="req.$$state.pending">
<img class="ajax-loader"
width="200"
height="200"
src="/images/spinner.gif" />
</div>
เชิงมุม:
$scope.req = $http.get("/admin/view/"+id).success(function(data) {
$scope.data = data;
});
ในขณะที่สัญญาที่ส่งคืนจาก $ http อยู่ระหว่างดำเนินการ ng-show จะประเมินว่าเป็น "ความจริง" สิ่งนี้จะได้รับการปรับปรุงโดยอัตโนมัติเมื่อสัญญาได้รับการแก้ไข ... ซึ่งเป็นสิ่งที่เราต้องการ
ใช้ intercepter ต่อไปนี้เพื่อแสดงแถบโหลดบนคำขอ http
'use strict';
appServices.factory('authInterceptorService', ['$q', '$location', 'localStorage','$injector','$timeout', function ($q, $location, localStorage, $injector,$timeout) {
var authInterceptorServiceFactory = {};
var requestInitiated;
//start loading bar
var _startLoading = function () {
console.log("error start loading");
$injector.get("$ionicLoading").show();
}
//stop loading bar
var _stopLoading = function () {
$injector.get("$ionicLoading").hide();
}
//request initiated
var _request = function (config) {
requestInitiated = true;
_startLoading();
config.headers = config.headers || {};
var authDataInitial = localStorage.get('authorizationData');
if (authDataInitial && authDataInitial.length > 2) {
var authData = JSON.parse(authDataInitial);
if (authData) {
config.headers.Authorization = 'Bearer ' + authData.token;
}
}
return config;
}
//request responce error
var _responseError = function (rejection) {
_stopLoading();
if (rejection.status === 401) {
$location.path('/login');
}
return $q.reject(rejection);
}
//request error
var _requestError = function (err) {
_stopLoading();
console.log('Request Error logging via interceptor');
return err;
}
//request responce
var _response = function(response) {
requestInitiated = false;
// Show delay of 300ms so the popup will not appear for multiple http request
$timeout(function() {
if(requestInitiated) return;
_stopLoading();
console.log('Response received with interceptor');
},300);
return response;
}
authInterceptorServiceFactory.request = _request;
authInterceptorServiceFactory.responseError = _responseError;
authInterceptorServiceFactory.requestError = _requestError;
authInterceptorServiceFactory.response = _response;
return authInterceptorServiceFactory;
}]);
.factory('authHttpResponseInterceptor', ['$q', function ($q) {
return {
request: function(config) {
angular.element('#spinner').show();
return config;
},
response : function(response) {
angular.element('#spinner').fadeOut(3000);
return response || $q.when(response);
},
responseError: function(reason) {
angular.element('#spinner').fadeOut(3000);
return $q.reject(reason);
}
};
}]);
.config(['$routeProvider', '$locationProvider', '$translateProvider', '$httpProvider',
function ($routeProvider, $locationProvider, $translateProvider, $httpProvider) {
$httpProvider.interceptors.push('authHttpResponseInterceptor');
}
]);
in your Template
<div id="spinner"></div>
css
#spinner,
#spinner:after {
border-radius: 50%;
width: 10em;
height: 10em;
background-color: #A9A9A9;
z-index: 10000;
position: absolute;
left: 50%;
bottom: 100px;
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
สร้างคำสั่งด้วยรหัสนี้:
$scope.$watch($http.pendingRequests, toggleLoader);
function toggleLoader(status){
if(status.length){
element.addClass('active');
} else {
element.removeClass('active');
}
}
อีกวิธีหนึ่งในการแสดงการโหลดระหว่างการเปลี่ยนแปลง URL ที่แตกต่างคือ:
$rootScope.$on('$locationChangeStart', function() {
$scope.loading++;
});
$rootScope.$on('$locationChangeSuccess', function() {
$timeout(function() {
$scope.loading--;
}, 300);
});
ng-show="loading"
และจากนั้นในมาร์กอัปเพียงแค่สลับปั่นด้วย
หากคุณต้องการที่จะแสดงบนร้องขออาแจ็กซ์เพียงแค่เพิ่มเมื่อร้องขอจะเริ่มต้นและจะจบลงเมื่อเพิ่ม$scope.loading++
$scope.loading--
คุณสามารถลองสิ่งนี้ได้เช่นกัน:
สร้างคำสั่ง:
myApp.directive('loader', function () {
return {
restrict: 'A',
scope: {cond: '=loader'},
template: '<span ng-if="isLoading()" class="soft"><span class="fa fa-refresh fa-spin"></span></span>',
link: function (scope) {
scope.isLoading = function() {
var ret = scope.cond === true || (
scope.cond &&
scope.cond.$$state &&
angular.isDefined(scope.cond.$$state.status) &&
scope.cond.$$state.status === 0
);
return ret;
}
}
};
});
จากนั้นคุณเพิ่มสิ่งนี้ลงใน mainCtrl
// Return TRUE if some request is LOADING, else return FALSE
$scope.isLoading = function() {
return $http.pendingRequests.length > 0;
};
และ HTML สามารถมีลักษณะเช่นนี้:
<div class="buttons loader">
<span class="icon" loader="isLoading()"></span>
</div>
วิธีต่อไปนี้จะจดบันทึกคำขอทั้งหมดและซ่อนเฉพาะเมื่อทำคำขอทั้งหมดเสร็จแล้ว:
app.factory('httpRequestInterceptor', function(LoadingService, requestCount) {
return {
request: function(config) {
if (!config.headers.disableLoading) {
requestCount.increase();
LoadingService.show();
}
return config;
}
};
}).factory('httpResponseInterceptor', function(LoadingService, $timeout, error, $q, requestCount) {
function waitAndHide() {
$timeout(function() {
if (requestCount.get() === 0){
LoadingService.hide();
}
else{
waitAndHide();
}
}, 300);
}
return {
response: function(config) {
requestCount.descrease();
if (requestCount.get() === 0) {
waitAndHide();
}
return config;
},
responseError: function(config) {
requestCount.descrease();
if (requestCount.get() === 0) {
waitAndHide();
}
var deferred = $q.defer();
error.show(config.data, function() {
deferred.reject(config);
});
return deferred.promise;
}
};
}).factory('requestCount', function() {
var count = 0;
return {
increase: function() {
count++;
},
descrease: function() {
if (count === 0) return;
count--;
},
get: function() {
return count;
}
};
})
เนื่องจากการทำงานของตำแหน่ง: แก้ไขเปลี่ยนแปลงเมื่อเร็ว ๆ นี้ผมก็มีความยากลำบากในการแสดงโหลด GIF ข้างต้นทุกองค์ประกอบเพื่อให้ฉันได้ใช้ของเชิงมุม inbuilt jQuery
html
<div ng-controller="FetchController">
<div id="spinner"></div>
</div>
css
#spinner {display: none}
body.spinnerOn #spinner { /* body tag not necessary actually */
display: block;
height: 100%;
width: 100%;
background: rgba(207, 13, 48, 0.72) url(img/loader.gif) center center no-repeat;
position: fixed;
top: 0;
left: 0;
z-index: 9999;
}
body.spinnerOn main.content { position: static;} /* and whatever content needs to be moved below your fixed loader div */
ตัวควบคุม
app.controller('FetchController', ['$scope', '$http', '$templateCache', '$location', '$q',
function($scope, $http, $templateCache, $location, $q) {
angular.element('body').addClass('spinnerOn'); // add Class to body to show spinner
$http.post( // or .get(
// your data here
})
.then(function (response) {
console.info('success');
angular.element('body').removeClass('spinnerOn'); // hide spinner
return response.data;
}, function (response) {
console.info('error');
angular.element('body').removeClass('spinnerOn'); // hide spinner
});
})
หวังว่าจะช่วย :)
คำตอบทั้งหมดหรือซับซ้อนหรือจำเป็นต้องตั้งค่าตัวแปรบางอย่างในทุกคำขอซึ่งเป็นการปฏิบัติที่ผิดมากถ้าเรารู้แนวคิดของ DRY ตัวอย่าง interceptor ง่าย ๆ ฉันตั้งค่าเมาส์เมื่อรอเมื่อ 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 บางส่วนที่แสดงตัวโหลด
Interceptor จะทำงานทุกครั้งที่โทร ajax ดังนั้นไม่จำเป็นต้องสร้างตัวแปรบูลีนพิเศษ($ scope.loading = true / false ฯลฯ )ในทุกการโทร http
นี่คือการใช้งานของฉันง่ายเหมือน ng-show และตัวนับคำร้องขอ
ใช้บริการใหม่สำหรับคำขอทั้งหมดไปที่ $ http:
myApp.service('RqstSrv', [ '$http', '$rootScope', function($http, $rootScope) {
var rqstService = {};
rqstService.call = function(conf) {
$rootScope.currentCalls = !isNaN($rootScope.currentCalls) ? $rootScope.currentCalls++ : 0;
$http(conf).then(function APICallSucceed(response) {
// Handle success
}, function APICallError(response) {
// Handle error
}).then(function() {
$rootScope.currentCalls--;
});
}
} ]);
จากนั้นคุณสามารถใช้ตัวโหลดฐานของคุณกับจำนวนการโทรปัจจุบัน:
<img data-ng-show="currentCalls > 0" src="images/ajax-loader.gif"/>
หากคุณต้องการแสดงโหลดเดอร์สำหรับการร้องขอการร้องขอ HTTP ทุกครั้งคุณสามารถใช้เครื่องดักฟังเชิงมุมเพื่อจัดการการโทรการร้องขอ 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>
ไม่จำเป็นต้องใช้คำสั่งไม่จำเป็นต้องซับซ้อน
นี่คือรหัสที่จะวางไว้ถัดจากปุ่มส่งหรือที่ใดก็ตามที่คุณต้องการให้สปินเนอร์เป็น:
<span ng-show="dataIsLoading">
<img src="http://www.nasa.gov/multimedia/videogallery/ajax-loader.gif" style="height:20px;"/>
</span>
แล้วในตัวควบคุมของคุณ:
$scope.dataIsLoading = true
let url = '/whatever_Your_URL_Is'
$http.get(url)
.then(function(response) {
$scope.dataIsLoading = false
})
นี่คือวิธีการแก้ปัญหาของฉันซึ่งฉันรู้สึกว่าง่ายมากที่อีกโพสต์ที่นี่ ไม่แน่ใจว่ามันเป็น "สวย" แต่มันแก้ไขปัญหาทั้งหมดของฉัน
ฉันมีรูปแบบ CSS ที่เรียกว่า "กำลังโหลด"
.loading { display: none; }
html สำหรับ div loading สามารถเป็นอะไรก็ได้ แต่ฉันใช้ไอคอน 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>
และในฟังก์ชั่นฉันเพิ่งตั้งให้โหลด
(function (angular) {
function MainController($scope) {
$scope.loading = true
ฉันใช้ SignalR ดังนั้นในฟังก์ชั่น hubProxy.client.allLocks (เมื่อเสร็จแล้วจะผ่านล็อค) ฉัน juts ใส่
$scope.loading = false
$scope.$apply();
สิ่งนี้จะซ่อน {{someField}} เมื่อเพจกำลังโหลดเนื่องจากฉันตั้งค่าคลาสการโหลดตามโหลดและ AngularJS จะลบออกหลังจากนั้น