Ajax 요청 시 Angularjs 로드 화면
Angularjs를 사용하여 Ajax 요청이 완료될 때까지 로드 화면(단순 스피너)을 표시해야 합니다.코드 스니펫으로 아이디어를 제안해 주세요.
데이터 로딩 상태를 나타내는 스코프 변수를 설정하는 대신 디렉티브가 모든 것을 수행하도록 하는 것이 좋습니다.
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();
}
});
}
};
}]);
이 지시문에서는 로드하는 애니메이션 요소에 '로드' 속성을 부여하기만 하면 됩니다.
<div class="loading-spiner-holder" data-loading ><div class="loading-spiner"><img src="..." /></div></div>
페이지에 여러 개의 로드 스피너가 있을 수 있습니다.이러한 스피너를 어디에 어떻게 배치하는지는 사용자에게 달려 있으며 디렉티브는 자동으로 켜지거나 꺼집니다.
여기 예가 있어요.간단한 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>
각도
$scope.clickMe = function() {
$scope.loading = true;
$http.get('test.json')
.success(function(data) {
$scope.cars = data[0].cars;
$scope.loading = false;
});
}
물론 loading box html 코드를 디렉티브로 이동하고 $scope.loading에 $watch를 사용할 수 있습니다.이 경우:
HTML:
<loading></loading>
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();
});
}
}
})
PLUNK: http://plnkr.co/edit/AI1z21?p=preview
여기에는 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();
});
});
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();
});
};
컨트롤러 종속성에 'ngProgress'를 추가한 후 사용하십시오.또한 여러 AJAX 요청을 수행하는 경우 메인 앱 범위에서 증분 변수를 사용하여 'ngProgress.complete();'를 호출하기 전에 AJAX 요청이 언제 완료되었는지 추적합니다.
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;
}
};
});
}]);
그런 다음 $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();
}
});
}
};
});
이를 위한 최선의 방법은 커스텀 디렉티브와 함께 응답 인터셉터를 사용하는 것입니다.또한 $rootScope를 사용하는 pub/sub 메커니즘을 사용하여 프로세스를 더욱 개선할 수 있습니다.$broadcast 및 $rootScope.$on 메서드
그 모든 과정이 잘 쓰여진 블로그 기사에 기록되어 있기 때문에, 나는 여기서 그것을 반복하지 않을 것이다.필요한 실장을 작성하려면 , 그 문서를 참조해 주세요.
이 답변을 참고하여
https://stackoverflow.com/a/17144634/4146239
저에게 가장 좋은 솔루션은 jQuery를 사용하지 않는 방법이 있습니다.
.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)
scope.loadingStatus = 'true';
else
scope.loadingStatus = 'false';
});
}
}
})
.controller('myController', function($scope, $http) {
$scope.cars = [];
$scope.clickMe = function() {
scope.loadingStatus = 'true'
$http.get('test.json')
.success(function(data) {
$scope.cars = data[0].cars;
$scope.loadingStatus = 'false';
});
}
});
<body ng-app="myApp" ng-controller="myController" ng-init="loadingStatus='true'">
<loading ng-show="loadingStatus" ></loading>
<div ng-repeat="car in cars">
<li>{{car.name}}</li>
</div>
<button ng-click="clickMe()" class="btn btn-primary">CLICK ME</button>
</body>
$(element)를 교환해야 합니다.show(); 및 (실행)show(); $scope.loadingStatus = 'true'; 및 $scope.loadingStatus = 'false';
다음으로 이 변수를 사용하여 요소의 ng-show Atribut을 설정해야 합니다.
타이프스크립트 및 각도 구현
지시의
((): void=> {
"use strict";
angular.module("app").directive("busyindicator", busyIndicator);
function busyIndicator($http:ng.IHttpService): ng.IDirective {
var directive = <ng.IDirective>{
restrict: "A",
link(scope: Scope.IBusyIndicatorScope) {
scope.anyRequestInProgress = () => ($http.pendingRequests.length > 0);
scope.$watch(scope.anyRequestInProgress, x => {
if (x) {
scope.canShow = true;
} else {
scope.canShow = false;
}
});
}
};
return directive;
}
})();
범위
module App.Scope {
export interface IBusyIndicatorScope extends angular.IScope {
anyRequestInProgress: any;
canShow: boolean;
}
}
템플릿
<div id="activityspinner" ng-show="canShow" class="show" data-busyindicator>
</div>
CSS
#activityspinner
{
display : none;
}
#activityspinner.show {
display : block;
position : fixed;
z-index: 100;
background-image : url('data:image/gif;base64,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')
-ms-opacity : 0.4;
opacity : 0.4;
background-repeat : no-repeat;
background-position : center;
left : 0;
bottom : 0;
right : 0;
top : 0;
}
Resangular(대단한)를 사용하는 경우 API 호출 중에 애니메이션을 만들 수 있습니다.제 해결책은 이렇습니다.응답 인터셉터와 루트 스코프 브로드캐스트를 송신하는 요구 인터셉터를 추가합니다.그런 다음 해당 응답과 요청을 수신하는 지시문을 작성합니다.
angular.module('mean.system')
.factory('myRestangular',['Restangular','$rootScope', function(Restangular,$rootScope) {
return Restangular.withConfig(function(RestangularConfigurer) {
RestangularConfigurer.setBaseUrl('http://localhost:3000/api');
RestangularConfigurer.addResponseInterceptor(function(data, operation, what, url, response, deferred) {
var extractedData;
// .. to look for getList operations
if (operation === 'getList') {
// .. and handle the data and meta data
extractedData = data.data;
extractedData.meta = data.meta;
} else {
extractedData = data.data;
}
$rootScope.$broadcast('apiResponse');
return extractedData;
});
RestangularConfigurer.setRequestInterceptor(function (elem, operation) {
if (operation === 'remove') {
return null;
}
return (elem && angular.isObject(elem.data)) ? elem : {data: elem};
});
RestangularConfigurer.setRestangularFields({
id: '_id'
});
RestangularConfigurer.addRequestInterceptor(function(element, operation, what, url) {
$rootScope.$broadcast('apiRequest');
return element;
});
});
}]);
지시사항은 다음과 같습니다.
angular.module('mean.system')
.directive('smartLoadingIndicator', function($rootScope) {
return {
restrict: 'AE',
template: '<div ng-show="isAPICalling"><p><i class="fa fa-gear fa-4x fa-spin"></i> Loading</p></div>',
replace: true,
link: function(scope, elem, attrs) {
scope.isAPICalling = false;
$rootScope.$on('apiRequest', function() {
scope.isAPICalling = true;
});
$rootScope.$on('apiResponse', function() {
scope.isAPICalling = false;
});
}
};
})
;
"app.config"에 다음 내용을 포함합니다.
$httpProvider.interceptors.push('myHttpInterceptor');
다음 코드를 추가합니다.
app.factory('myHttpInterceptor', function ($q, $window,$rootScope) {
$rootScope.ActiveAjaxConectionsWithouthNotifications = 0;
var checker = function(parameters,status){
//YOU CAN USE parameters.url TO IGNORE SOME URL
if(status == "request"){
$rootScope.ActiveAjaxConectionsWithouthNotifications+=1;
$('#loading_view').show();
}
if(status == "response"){
$rootScope.ActiveAjaxConectionsWithouthNotifications-=1;
}
if($rootScope.ActiveAjaxConectionsWithouthNotifications<=0){
$rootScope.ActiveAjaxConectionsWithouthNotifications=0;
$('#loading_view').hide();
}
};
return {
'request': function(config) {
checker(config,"request");
return config;
},
'requestError': function(rejection) {
checker(rejection.config,"request");
return $q.reject(rejection);
},
'response': function(response) {
checker(response.config,"response");
return response;
},
'responseError': function(rejection) {
checker(rejection.config,"response");
return $q.reject(rejection);
}
};
});
각도 비지 사용:
앱/모듈에 cgBusy 추가:
angular.module('your_app', ['cgBusy']);
★★★★★★★★★★★★★★★★★★★에 약속 추가scope
:
function MyCtrl($http, User) {
//using $http
this.isBusy = $http.get('...');
//if you have a User class based on $resource
this.isBusy = User.$save();
}
html 템플릿:
<div cg-busy="$ctrl.isBusy"></div>
,, 용, 용, 용, 사, 사, ,, ,, ,, also, also, also, also, also, also, also, also, also, also, also, also, also, also, that, alsoAngularjs
애니메이션이 포함되어 있습니다.
링크가 여기에 있습니다(왼쪽 상단 모서리 참조).
오픈 소스입니다.다운로드 링크입니다.
튜토리얼 링크입니다.
제 요점은 소스 파일을 다운로드하여 스피너를 어떻게 구현했는지 보는 것입니다.좀 더 나은 어프로치를 사용했을지도 몰라이 프로젝트를 확인해 보세요.
간단한 가로채기 예에서는 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 콜에서 실행되므로 모든 http 콜에서 특별한 부울 변수($sube.loading=true/false 등)를 작성할 필요가 없습니다.
대행 수신기는 angular jqLite https://docs.angularjs.org/api/ng/function/angular.element에 내장된 기능을 사용하기 때문에 Jquery는 필요하지 않습니다.
show 속성 및 size 속성을 사용하여 디렉티브를 만듭니다(추가할 수도 있습니다).
app.directive('loader',function(){
return {
restrict:'EA',
scope:{
show : '@',
size : '@'
},
template : '<div class="loader-container"><div class="loader" ng-if="show" ng-class="size"></div></div>'
}
})
및 html로 사용합니다.
<loader show="{{loader1}}" size="sm"></loader>
show variable에서는 약속이 실행 중일 때는 true를 통과시키고 요구가 완료되면 false를 통과시킵니다.활성 데모 - JsFiddle의 Angular Loader 지시어 예제 데모
@DavidLin의 답변을 바탕으로 jQuery에 대한 지시가 없어졌습니다.실제 어플리케이션에서 사용하므로 동작하는 것을 확인할 수 있습니다.
function AjaxLoadingOverlay($http) {
return {
restrict: 'A',
link: function ($scope, $element, $attributes) {
$scope.loadingOverlay = false;
$scope.isLoading = function () {
return $http.pendingRequests.length > 0;
};
$scope.$watch($scope.isLoading, function (isLoading) {
$scope.loadingOverlay = isLoading;
});
}
};
}
사용하고 있습니다.ng-show
jQuery 호출 대신 jQuery 호출을 사용하여 숨김/표시합니다.<div>
.
여기 있습니다.<div>
개구부 바로 아래에 두었습니다.<body>
태그:
<div ajax-loading-overlay class="loading-overlay" ng-show="loadingOverlay">
<img src="Resources/Images/LoadingAnimation.gif" />
</div>
$http 콜이 발신되는 동안 UI를 차단하기 위한 오버레이를 제공하는 CSS는 다음과 같습니다.
.loading-overlay {
position: fixed;
z-index: 999;
height: 2em;
width: 2em;
overflow: show;
margin: auto;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
.loading-overlay:before {
content: '';
display: block;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.3);
}
/* :not(:required) hides these rules from IE9 and below */
.loading-overlay:not(:required) {
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
CSS 크레딧은 @Steve Seeger's - 그의 투고:https://stackoverflow.com/a/35470281/335545
조건을 추가한 후 루트 스코프를 통해 변경할 수 있습니다.ajax 요청 전에 $rootScope를 호출하기만 하면 됩니다.$emit('stopLoader');
angular.module('directive.loading', [])
.directive('loading', ['$http', '$rootScope',function ($http, $rootScope)
{
return {
restrict: 'A',
link: function (scope, elm, attrs)
{
scope.isNoLoadingForced = false;
scope.isLoading = function () {
return $http.pendingRequests.length > 0 && scope.isNoLoadingForced;
};
$rootScope.$on('stopLoader', function(){
scope.isNoLoadingForced = true;
})
scope.$watch(scope.isLoading, function (v)
{
if(v){
elm.show();
}else{
elm.hide();
}
});
}
};
}]);
이것은 확실히 최선의 해결책은 아니지만 여전히 효과가 있을 것이다.
언급URL : https://stackoverflow.com/questions/17144180/angularjs-loading-screen-on-ajax-request
'source' 카테고리의 다른 글
AngularJS: ngIf를 명령어에 프로그래밍 방식으로 추가하는 베스트 프랙티스는 무엇입니까? (0) | 2023.03.13 |
---|---|
Spring-Data JPA CrudRepository는 Itable을 반환합니다.목록에 캐스팅해도 될까요? (0) | 2023.03.13 |
ExtJS 철학이란?한 페이지 어플리케이션? (0) | 2023.03.13 |
Python에서 Oracle에 액세스하려면 어떻게 해야 합니까? (0) | 2023.03.13 |
python으로 json 파일을 업데이트하는 방법 (0) | 2023.03.13 |