Подтвердить что ты не робот

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 пуст, счетчик заменяется ничем.

Как я должен делать это чисто?

4b9b3361

Ответ 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);
});