Используя Angularjs, мне нужно показать экран загрузки (простой счетчик) до тех пор, пока не будет завершен запрос ajax. Пожалуйста, предложите любую идею с фрагментом кода.Экран загрузки 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>
На странице может быть несколько загрузочных прядильщиков. где и как правильно расположить эти прядильщики, и директива просто включит/выключит вас автоматически.
здесь директива "loading" вызывается дважды, с $ location.path(). Сначала с текущей страницей и рядом с целевой страницей. В чем причина? –
Отлично. Кроме того, вы можете использовать jquery toggle на watch: elm.toggle (v). У меня есть контрольный сеанс сеанса ожидания, и для меня мне нужно показать счетчик только через полсекунды. Я буду использовать css с переходом, чтобы медленнее показывать счетчик. –
Если вы получаете ошибку «elm.show() не является функцией», перед загрузкой нужно добавить jquery. – morpheus05
Вот пример. Он использует простой метод 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>
ANGULARJS
$scope.clickMe = function() {
$scope.loading = true;
$http.get('test.json')
.success(function(data) {
$scope.cars = data[0].cars;
$scope.loading = false;
});
}
Конечно, вы можете переместить HTML-код загрузки коробки в директиву, а затем использовать $ смотреть на $ scope.loading. В этом случае:
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();
});
}
}
})
шлепнуть: http://plnkr.co/edit/AI1z21?p=preview
Спасибо, что разделили примеры директив - хорошо ответ на общий подход :) – kontur
То, как вы делаете scope.watch, работает для меня, потому что принятый подход ответа не делает. – KingOfHypocrites
Работает отлично. Престижность за подробное объяснение! – Gene
Также есть хороший демо, что показывает, как можно вы используете Angularjs
анимация в вашем проекте.
Ссылка есть
http://yearofmoo-articles.github.io/angularjs-animation-article/app/#/ng-repeat (См. Верхний левый угол).
Это открытый источник. вот ссылка для скачивания
https://github.com/yearofmoo-articles/AngularJS-Animation-Article
И вот ссылка для учебника;
http://www.yearofmoo.com/2013/04/animation-in-angularjs.html
Я хочу сказать, продолжайте и загрузите исходные файлы, а затем посмотрите, как они реализовали счетчик. Возможно, они использовали немного лучше. Итак, проверьте этот проект.
Лучший способ сделать это - использовать ответные перехватчики вместе с пользовательским директивой. И этот процесс можно дополнительно улучшить, используя pub/sub механизм с использованием $ rootScope. $ Broadcast & $ rootScope. $ On методы.
Как весь процесс документирован в хорошо написанном blog article, я не буду повторять это здесь снова. Пожалуйста, обратитесь к этой статье, чтобы придумать необходимую вам реализацию.
Я использую ngProgress для этого.
Добавьте 'ngProgress' к вашим зависимостям, как только вы включили файлы сценария/css в свой HTML. После этого вы можете настроить что-то вроде этого, которое будет срабатывать при обнаружении изменения маршрута.
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, используйте инкрементную переменную в основной области приложения, чтобы отслеживать, когда ваши запросы AJAX завершились до вызова 'ngProgress.complete();'.
Wow. Это фантастика. Спасибо. – Fortin
с использованием ожидающих запросов Requests неверен, поскольку, как указано в Угловой документации, это свойство в основном предназначено для использования в целях отладки.
Я рекомендую использовать перехватчик, чтобы узнать, есть ли активный Асинхронный вызов.
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;
}
};
});
}]);
, а затем проверить, является ли activeCalls нулевым или нет в директиве через $ watch.
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();
}
});
}
};
});
Если вы используете Restangular (что удивительно), вы можете создать анимацию во время вызовов 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;
});
}
};
})
;
Любой ответ API будет убивать анимацию. Вы должны хранить дополнительную информацию о запросе-ответе и реагировать только на тот ответ, который был инициализирован по запросу. –
Включите это в "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);
}
};
});
В отношении этого ответа
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>
Вам нужно заменить $ (элемент) .show(); и (element) .show(); с $ scope.loadingStatus = 'true'; и $ scope.loadingStatus = 'false';
Чтобы использовать атрибут ng-show элемента, вам необходимо использовать эту переменную.
Машинопись и Угловое Реализация
директива
((): 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;
}
Благодарим вас за это! Примеры js раздражают, чтобы перевести ... – daark
Вы спасли мой день, спасибо! :) – Lightning3
Использование angular-busy:
Добавить 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>
Я построил на @ 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, чтобы скрыть/показать <div>
.
Вот <div>
, который я поставил чуть ниже отверстия <body>
тег:
<div ajax-loading-overlay class="loading-overlay" ng-show="loadingOverlay">
<img src="Resources/Images/LoadingAnimation.gif" />
</div>
И вот CSS, который обеспечивает наложение блокировать пользовательский интерфейс в то время как $ HTTP вызов был сделан:
.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
Здесь простой пример перехватчика, я установил мышь в ожидании w При запуске 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-вызова.
Перехватчик использует встроенный угловой jqLitehttps://docs.angularjs.org/api/ng/function/angular.element так что нет необходимости в JQuery.
Создать директиву с шоу и размера атрибутов (вы можете добавить еще больше)
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>
В показать прохода переменной истинное когда любое обещание выполняется и делает это false, когда запрос будет выполнен. Активный демо - Angular Loader directive example demo in JsFiddle
Вы можете добавить условие, а затем изменить его с помощью rootscope. Перед вашим запросом 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();
}
});
}
};
}]);
Это определенно не самое лучшее решение, но он все равно работает.
- 1. AJAX сортировать по запросу
- 2. ERR_CONTENT_LENGTH_MISMATCH по запросу ajax
- 3. Загрузить вкладки Ajax по запросу
- 4. Содержимое загрузки UIWebView по запросу
- 5. Передача Angularjs и по запросу
- 6. Autocomplete по запросу в angularJS
- 7. Выполнить директиву AngularJS по запросу
- 8. Вопрос по запросу Ajax (Liferay)
- 9. Обработка данных по запросу AJAX
- 10. Значок CSRF по запросу ajax
- 11. Decode JSON по запросу Ajax
- 12. jQuery Loader по запросу Ajax
- 13. Возвращаемые данные по запросу AJAX
- 14. use require_once по запросу ajax
- 15. Символ symfony2 csrf недействителен по запросу ajax
- 16. Как создать экран загрузки между маршрутами angularJs
- 17. Проблема подкачки кендо по запросу ajax
- 18. Отобразить результаты расчета по запросу AJAX
- 19. Экран загрузки jquery на вызов ajax
- 20. Библиотека JavaScript для загрузки ресурсов по запросу?
- 21. AngularJS загрузка содержимого HTML div по запросу
- 22. angularjs обновить переменную информацию по запросу
- 23. Ошибка сертификата Кордовы по запросу angularjs https
- 24. Проблемы со сценарием по запросу ajax
- 25. Select2 - Ajax Data - Populate Распаковка по запросу
- 26. jQuery потерять значение $ (this) по запросу ajax
- 27. Можно ли отправлять заголовки по запросу AJAX?
- 28. Почему setTimeout не работает по запросу AJAX?
- 29. AJAX использует старые данные по запросу
- 30. Facebook Like Button Отключен по запросу AJAX
см. Http://stackoverflow.com/questions/15033195/showing-spinner-gif-during-http-request-in-angular –
http://angulartutorial.blogspot.in/2014/04/ angular-loader-using-font-awesome-icons.html – Prashobh
Лучшая практика заключается в использовании '$ httpProvider.interceptors', поскольку она может обрабатывать, когда запускается запрос ajax и когда он заканчивается. Вот почему '$ watch' больше не требуется, чтобы обнаруживать, когда начало и конец запуска ajax. –