Показать активность Индикатор при загрузке ленивого загруженного модуля в угловом 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
вы можете сделать это так
- в app.component.html
<div class="main-loader" *ngIf="loading">
<div class="cssload-container" >
<div class="cssload-whirlpool"></div>
</div>
</div>
-
в 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
});
}
-
в 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);
}