Angularjs: Как отображать значок загрузки при использовании "разрешения" в $routeProvider?
Следующий код читает через службу и показывает на веб-странице список объектов "страницы" для определенной "категории страниц" (строка). Используя свойство объекта разрешения в $routeProvider.when(), я могу отложить обновление представления до тех пор, пока новое значение не будет готово.
Два вопроса:
-
При запросе нового списка страниц я хочу показать значок загрузки. Как я могу обнаружить (не хакерским способом) событие, когда начинается чтение с сервера (и значок загрузки)? Я предполагаю, что я мог бы сделать что-то вроде $('. Pages-loading-icon'). Show() в службе, но обнаружил, что слишком слишком зависим от gui, помещенный в службу.
-
Когда новое значение будет готово, я хотел бы, чтобы старый погас, и новый, чтобы исчезнуть. Что такое способ angular? Я попытался сделать это в контроллере с помощью $watch, но это приводит к тому, что новое значение будет отображаться незадолго до запуска fadeout.
Код:
app.js:
$routeProvider.when('/:cat', { templateUrl: 'partials/view.html', controller: RouteCtrl, resolve: RouteCtrl.resolve});
controllers.js:
function RouteCtrl($scope, $routeParams, pages) {
$scope.params = $routeParams;
$scope.pages = pages;
}
RouteCtrl.resolve={
pages: function($routeParams, Pages){
if($routeParams.hasOwnProperty('cat')){
return Pages.query($routeParams.cat);
}
}
}
services.js:
Последние прочитанные страницы хранятся в currentPages и его категории в lastCat.
factory('Pages', function($resource, $q, $timeout){
return {
res: $resource('jsonService/cat=:cat', {}, {
query: {method:'GET', params:{cat:'cat'}, isArray:true}
}),
lastCat: null,
currentPages: null,
query: function(cat) {
var res = this.res;
if(cat != this.lastCat){
var deferred = $q.defer();
var p = res.query({'cat':cat}, function(){
deferred.resolve(p);
});
this.lastCat = cat;
this.currentPages = deferred.promise;
}
return this.currentPages;
}
};
})
view.html
<ul >
<li ng-repeat="page in pages">
<a href="#{{params.cat}}/{{page.slug}}">{{page.title}}</a>
</li>
</ul>
Ответы
Ответ 1
Не совсем уверен, будет ли это работать в вашем коде, поскольку у вас есть интеграция ресурсов.
Но, возможно, стоит посмотреть на события angular: $routeChangeStart
и $routeChangeSuccess
.
в html:
<span ng-show="isViewLoading"> loading the view... </span>
в контроллере (который определяет область действия html выше):
$scope.isViewLoading = false;
$scope.$on('$routeChangeStart', function() {
$scope.isViewLoading = true;
});
$scope.$on('$routeChangeSuccess', function() {
$scope.isViewLoading = false;
});
$scope.$on('$routeChangeError', function() {
$scope.isViewLoading = false;
});
Ответ 2
Система маршрутизации для angular кажется немного ограниченной..
Это решило это для меня:
http://www.bennadel.com/blog/2420-Mapping-AngularJS-Routes-Onto-URL-Parameters-And-Client-Side-Events.htm
Кроме того, о событиях, запускаемых дважды: если вы настроили маршрут, перейдите к "a/b/c" angular, автоматически настройте другой маршрут, "a/b/c/" (с завершающей косой чертой) для перенаправления к первому (и наоборот), и к двум событиям запуска. Я просто проверяю наличие параметров маршрута.
Относительно ограниченного состояния системы маршрутизации: this pull от angular, чтобы расширить возможности.
Ответ 3
Мне нравится 'ng-show'
... Но 'ui-if'
проекта пользовательского интерфейса Angular лучше IMHO.. Так как удалите HTML-код из DOM...
<span ui-if = "isViewLoading"> loading the view... </span>
_e
Ответ 4
Вы также можете использовать директиву ng-show. Просто проверьте, пуста ли модель, и отобразите подмножество DOM следующим образом:
<!-- model not ready -->
<div style="width: 200" ng-show="lines == ''">
<div class="progress progress-striped active">
<div class="bar" style="width: 0%;"></div>
</div>
</div>
<!-- your model code -->
<ul class="nav nav-tabs nav-stacked">
<li ng-repeat="line in lines">
{{line.Id}}
</li>
</ul>
Ответ 5
Вы хотите использовать $rootScope
, потому что контроль контроллера $scope
ограничивается контроллером, и, как это происходит, вы переключаетесь с одного вида (один контроллер) на другой вид (другой контроллер). Таким образом, имеет смысл иметь один-кодовое соответствие.
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams){ ... })
В этой функции установите $rootScope.isLoadingState
, который отобразит ваш индикатор загрузки.
Затем используйте
$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, fromState, fromParams){ ... })
Чтобы отключить эту переменную.
Заполните ссылку здесь
Ответ 6
Вы можете создать директиву, которая будет отображаться на основе широковещательной передачи, которую вы отправляете до и после вызова службы, которую вы можете наложить на $rootScope. Поэтому, если вы вызываете factory, чтобы обрабатывать общие вызовы POST/GET, а прямо перед вызовом вы можете вызвать функцию на $rootScope, например "$ rootScope.startLoading()", и когда он заканчивает вызов "$ rootScope.doneLoading()", где каждый из этих методов транслирует событие, чтобы вы могли выбрать свою директиву. Затем вы просто обрабатываете свою директиву, чтобы поймать события: "scope. $On" ( "startLoading", func (... ", и пусть он вставляет/показывает загрузочный div-шаблон в DOM и запускается, а затем также имеет catch для сделать загрузку, чтобы удалить/скрыть ее.
Таким образом, вы можете иметь хороший общий накладной загрузки.