Angular js - show/hide loading gif каждый новый маршрут

Я пытаюсь переключить (скрыть/показать) загрузку gif на каждый новый маршрут, поэтому моя логика:

  • routeChangeStart = показать загрузку gif
  • routeChangeSuccess = скрыть загрузку gif

Это мой код:

//ANGULAR
app.run(function($rootScope) {

   $rootScope.layout = {};
   $rootScope.layout.loading = false; 

   $rootScope.$on('$routeChangeStart', function() {

      //show loading gif
      $rootScope.layout.loading = true;

   });

   $rootScope.$on('$routeChangeSuccess', function() {

      //hide loading gif
      $rootScope.layout.loading = false;

   });

   $rootScope.$on('$routeChangeError', function() {

       //hide loading gif
       alert('wtff');
       $rootScope.layout.loading = false;
   });
});

//HTML

<img src="img/loading.gif" ng-hide="!layout.loading"/>

Это странно, потому что это работает для 3/4 маршрутов, которые изменились, а затем перестали работать при изменении маршрутов: O

что это может быть?

ЗДЕСЬ ЖИВОЙ ПРИМЕР благодаря @Rob Sedgwick: http://plnkr.co/edit/ZpkgRhEAoUGlnXjbLb8b

Ответ 1

Короткий ответ: $rootScope.layout.loading изменился, как ожидалось. Но если шаблоны загружены, браузер не успевает сделать изменения видимыми.

Длинный ответ: если вы поставите console.log выходы в ваших $on слушателей, вы увидите, что $routeChangeStart срабатывает событие, шаблон загружается и после этого $routeChangeSuccess пожары. Под капотом происходит следующее:

  • $routeChangeStart срабатывает
  • $rootScope.layout.loading становится true
  • шаблон загружается асинхронно
  • обновлен DOM
  • браузер отображает загрузку gif

немного позже (возвращается запрос xhr)

  • был загружен шаблон
  • $routeChangeSuccess срабатывает
  • $rootScope.layout.loading становится false
  • обновлен DOM
  • браузер больше не показывал gif

что произойдет, если tmeplates будут кешированы: - $routeChangeStart пожары - $rootScope.layout.loading становится true - $routeChangeSuccess пожары - $rootScope.layout.loading становится false - DOM обновляется (но это то же самое состояние, что и раньше)

Как вы можете видеть, браузер не может отобразить новое состояние, потому что работает script, который не прерывается, чтобы дать браузеру время для рендеринга DOM. Если шаблон еще не загружен, запросы ajax останавливают выполнение script и дают время браузера для отображения DOM.

Как это исправить?

Вы можете использовать timeout, которые дают время браузера для обновления DOM:

$rootScope.$on('$routeChangeSuccess', function () {
    console.log('$routeChangeSuccess');
    //hide loading gif
    $timeout(function(){
      $rootScope.layout.loading = false;
    }, 200);
});

Вот ваш plunkr с этим решением: http://plnkr.co/edit/MkREo0Xpz5SUWg0lFCdu?p=preview

Ответ 2

(Немного слишком много, чтобы добавить комментарий)

Я установил код и увидел, что переменная загрузки не обновлялась каждый раз и была связана с кэшированием шаблонов, я думаю, что "RouteChange" не запускается.

Отключение кэширования шаблонов позволит вашему коду запускаться каждый раз.

app.run(function($rootScope, $location, $anchorScroll, $routeParams,$templateCache) {

   $rootScope.$on('$viewContentLoaded', function() {
       $templateCache.removeAll();
    });

   ....