AngularJS: показывать загрузку HTML до загрузки данных
Как я могу заставить AngularJS показывать счетчик загрузки до тех пор, пока данные не закончили загрузку?
Если мой контроллер имеет статическую установку $scope.items = [{name: "One"}]
и загрузчик AJAX, который заполняет $scope.items[0]['lateLoader'] = "Hello"
, я бы хотел, чтобы spinner отображался до завершения загрузки AJAX, а затем заполнял связанный диапазон с помощью полученных данных.
<ul ng-repeat="item in items">
<li>
<p>Always present: {{item.name}}</p>
<p>Loads later: <span ng-bind="item.lateLoader"><i class="icon icon-refresh icon-spin"></i></span></p>
</li>
</ul>
Этот код немедленно заполняет связанный диапазон, а поскольку item.lateLoader
пуст, счетчик заменяется ничем.
Как я должен делать это чисто?
Ответы
Ответ 1
Я бы создал пользовательскую директиву в соответствии с другим ответом, но вот как вы могли бы это сделать без директивы, которая может быть хорошей идеей для изучения, прежде чем перейти к более сложной функциональности. Несколько замечаний:
- Использование setTimeout для имитации вызова ajax
- Значок загрузки предварительно загружается и скрывается при загрузке данных. Просто простая директива ng-hide.
- В моем примере нет загрузочного изображения, который будет скрыт (очевидно, ваш html будет иметь правильные ссылки css).
Демо: http://plnkr.co/edit/4XZJqnIpie0ucMNN6egy?p=preview
Вид:
<ul >
<li ng-repeat="item in items">
<p>Always present: {{item.name}}</p>
<p>Loads later: {{item.lateLoader}} <i ng-hide="item.lateLoader" class="icon icon-refresh icon-spin">loading image i don't have</i></p>
</li>
</ul>
Контроллер:
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.items = [{name: "One"}];
setTimeout(function() {
$scope.$apply(function() {
$scope.items[0].lateLoader = 'i just loaded';
});
}, 1000);
});
Ответ 2
Я действительно использовал какое-то решение для этого какое-то время, которое отлично работает и лучше, чем использование тайм-аута, на мой взгляд. Я использую $resource, но вы можете сделать то же самое с $http. На объектах $resource я добавляю бит в следующий код, который устанавливает значение true.
$scope.customer = $resource(dataUrl + "/Course/Social/" + courseName)
.get({}, function (data) { data.loaded = true; });
Тогда, на мой взгляд, я могу использовать:
ng-hide="customer.loaded"
Конечно, я бы не использовал $resource непосредственно в контроллере, я извлекаю его в службу customerRepository, но было проще показать это здесь.
Ответ 3
Я бы создал пользовательскую директиву и поместил разметку по умолчанию с помощью spinner.
Вот некоторые ссылки на пользовательские директивы
1) Видео Egghead - это потрясающе! http://www.egghead.io/video/xoIHkM4KpHM
2) Официальные Angular документы по директивам http://docs.angularjs.org/guide/directive
3) Хороший обзор Angular за 60 минут http://weblogs.asp.net/dwahlin/archive/2013/04/12/video-tutorial-angularjs-fundamentals-in-60-ish-minutes.aspx
Ответ 4
@lucuma,
Отличный ответ, альтернативой может быть вложение $timeout и замена встроенной функции таймаута:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $timeout) {
$scope.name = 'World';
$scope.items = [{name: "One"}];
$timeout(function() {
$scope.$apply(function() {
$scope.items[0].lateLoader = 'i just loaded';
});
}, 1000);
});