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

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

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

Есть идеи?

Ответ 1

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

  • 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

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

<router-outlet></router-outlet>

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

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

Ответ 2

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

  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 любая анимация загрузки

надеюсь, это вам полезно. благодаря

Ответ 3

Вы можете просто использовать 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

Ответ 4

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

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>

Ответ 5

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

В моем переключателе clickItem нажмите событие:

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

    //let give time to tortoise IE11 to render loader before navigation...
    let obj = this;
    setTimeout(function() 
    {
      obj.router.navigateByUrl(url);
    }, 1);
  }