Angular 4: Moving Route
I am trying to create a simple boolean flag component isLoading
that true
when the route took more than half a second to resolve.
I have a piece to turn it off:
this.router.events
.filter(event => event instanceof NavigationEnd || event instanceof NavigationCancel || event instanceof NavigationError)
.subscribe(event => this.isLoading = false);
But how can I say:
this.router.events
//given a NavigationStart
//If you don't see NavigationEnd/NavigationCancel/NavigationError within 500ms
.subscribe(event => this.isLoading = true);
source to share
this.router.events
.debounceTime(500)
.filter(event => event instanceof NavigationStart)
.subscribe(event => this.isLoading = true);
What does it say:
.debounceTime(500)
= if another event is raised before 500ms suppresses me
.filter(event => event instanceof NavigationStart)
= use NavigateStart only from events not followed by 500ms
.subscribe(event => this.isLoading = true);
= we now know it was a navigation launch that didn't run for 500ms so that we could launch the loading icon
source to share
I just did it without a dedicated timer:
constructor(private authService: AuthService,
private messageService: MessageService,
private router: Router) {
router.events.subscribe((routerEvent: Event) => {
this.checkRouterEvent(routerEvent);
});
}
checkRouterEvent(routerEvent: Event): void {
if (routerEvent instanceof NavigationStart) {
this.loading = true;
}
if (routerEvent instanceof NavigationEnd ||
routerEvent instanceof NavigationCancel ||
routerEvent instanceof NavigationError) {
this.loading = false;
}
}
And it works great. If the route is loading quickly, there is no counter. If the route recognizer takes a little time, a counter appears.
This code is from the "Angular Routing" Pluralsight course here: https://app.pluralsight.com/library/courses/angular-routing
source to share
I think for now I'm going to go with this solution:
ngOnInit() {
let timer: any;
this.router.events
.subscribe(event => {
if (event instanceof NavigationStart) {
clearTimeout(timer);
timer = setTimeout(() => this.isLoading = true, 250);
} else if (event instanceof NavigationEnd || event instanceof NavigationCancel || event instanceof NavigationError) {
clearTimeout(timer);
this.isLoading = false;
}
});
}
If anyone is posting about cleaning up RxJs I noticed that
edit: Based on @ KeniSteward answer, I was able to get this solution to work:
this.router.events
.filter(event => event instanceof NavigationStart || event instanceof NavigationEnd || event instanceof NavigationCancel || event instanceof NavigationError)
.debounceTime(250)
.filter(event => event instanceof NavigationStart)
.subscribe(event => this.isLoading = true);
this.router.events
.filter(event => event instanceof NavigationEnd || event instanceof NavigationCancel || event instanceof NavigationError)
.subscribe(event => this.isLoading = false);
edit # 2: Even cleaner -
this.router.events
.filter(event => event instanceof NavigationStart || event instanceof NavigationEnd || event instanceof NavigationCancel || event instanceof NavigationError)
.do(event => this.isLoading = false)
.debounceTime(250)
.filter(event => event instanceof NavigationStart)
.subscribe(event => this.isLoading = true);
source to share