Показывать индикатор активности при загрузке лениво загруженного модуля в Angular 2

Мой сценарий таков. У меня есть меню с несколькими вариантами. Каждое меню должно отображаться в зависимости от прав пользователя (уже решено), большинство пунктов меню инкапсулированы в виде модулей, и большинство модулей загружаются с отложенной загрузкой, поэтому, когда пользователь щелкает первый раз в пункте меню, он загружается (до все работает хорошо), теперь мое требование состоит в том, чтобы для лучшего взаимодействия с пользователем мне нужно было отображать индикатор активности после того, как пользователь щелкнет по пункту меню и загружается лениво загруженный модуль.

До этого я пытался использовать интерфейсы CanActive, canLoad, canActivateChild от Angular Router, но безуспешно,

Есть идеи?

5 ответов

Вы можете прослушать два события маршрутизатора:

  • RouteConfigLoadStart
  • RouteConfigLoadEnd

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

Слушайте их в своем корневом AppComponent, чтобы показать / скрыть свой счетчик.

app.component.ts

import { Router, RouteConfigLoadStart, RouteConfigLoadEnd } from '@angular/router';

...

export class AppComponent implements OnInit {

    loadingRouteConfig: boolean;

    constructor (private router: Router) {}

    ngOnInit () {
        this.router.events.subscribe(event => {
            if (event instanceof RouteConfigLoadStart) {
                this.loadingRouteConfig = true;
            } else if (event instanceof RouteConfigLoadEnd) {
                this.loadingRouteConfig = false;
            }
        });
    }
}

app.component.html

Здесь простая строка, но вы можете использовать компонент счетчика.

<router-outlet></router-outlet>

<ng-container *ngIf="loadingRouteConfig">Loading route config...</ng-container>

Я использую этот подход с Angular v4.2.3

Ты можешь сделать это так

  1. в app.component.html
<div class="main-loader" *ngIf="loading">
  <div class="cssload-container" >
      <div class="cssload-whirlpool"></div>
  </div>
</div>
  1. в app.component.ts

    import { Router, NavigationStart, NavigationEnd } from '@angular/router';
    
    
    loading:boolean = false;
    constructor(private router:Router) { 
      router.events.subscribe(event => {
        if(event instanceof NavigationStart) {
          this.loading = true;
          console.log("event started")
        }else if(event instanceof NavigationEnd) {
          this.loading = false;
          console.log("event end")
        }
        // NavigationEnd
        // NavigationCancel
        // NavigationError
        // RoutesRecognized
      });
    
    }
    
  2. в CSS любая анимация загрузки

надеюсь, что это полезно для вас. Спасибо

Вы можете просто использовать CSS!

<routler-outlet></routler-outlet>
<div class='.loader>
  Just, wait a sec ! I'm loading
</div>

В вашем шаблоне

router-outlet + .loader {
  opacity : 1;
}

.loader {
  opacity : 0;
}

Тогда вы можете создавать модные блесны с HTML/CSS

Можно нажать ссылку на другой ленивый маршрут при загрузке первого. Вот почему нам нужно подсчитывать загружаемые маршруты:

app.component.ts

`` `

export class AppComponent { 

  currentlyLoadingCount = this._router.events.scan((c, e) => this._countLoads(c, e), 0);

  constructor(private _router: Router) { }

  private _countLoads(counter: number, event: any): number {
    if (event instanceof RouteConfigLoadStart) return counter + 1;
    if (event instanceof RouteConfigLoadEnd) return counter - 1;
    return counter;
  }

`` `

app.component.html <ng-container *ngIf="currentlyLoadingCount | async">Loading route config...</ng-container>

Для тех, кому нужна совместимость (и работа с) с IE11, принятый ответ не работает, потому что IE11 не отображает загрузчик при переключении с одного модуля на другой, поэтому я сделал (не очень элегантный, но работающий) обходной путь:

В моем menuItem переключатель щелчка события:

  public navigate(url: string) {
    this.configurationService.loading = true; //service variable linked with html loader

    //let's give time to tortoise IE11 to render loader before navigation...
    let obj = this;
    setTimeout(function() 
    {
      obj.router.navigateByUrl(url);
    }, 1);
  }
Другие вопросы по тегам