I have a global loader which is implemented like this:
CoreModule:
router.events.pipe( filter(x => x instanceof NavigationStart) ).subscribe(() => loaderService.show()); router.events.pipe( filter(x => x instanceof NavigationEnd || x instanceof NavigationCancel || x instanceof NavigationError) ).subscribe(() => loaderService.hide());
LoaderService:
@Injectable({ providedIn: 'root' }) export class LoaderService { overlayRef: OverlayRef; componentFactory: ComponentFactory<LoaderComponent>; componentPortal: ComponentPortal<LoaderComponent>; componentRef: ComponentRef<LoaderComponent>; constructor( private overlay: Overlay, private componentFactoryResolver: ComponentFactoryResolver ) { this.overlayRef = this.overlay.create( { hasBackdrop: true, positionStrategy: this.overlay.position().global().centerHorizontally().centerVertically() } ); this.componentFactory = this.componentFactoryResolver.resolveComponentFactory(LoaderComponent); this.componentPortal = new ComponentPortal(this.componentFactory.componentType); } show(message?: string) { this.componentRef = this.overlayRef.attach<LoaderComponent>(this.componentPortal); this.componentRef.instance.message = message; } hide() { this.overlayRef.detach(); } }
When running with Angular 7.0.2, the behavior (which I wanted) was:
I have updated to Angular 7.2, now the behavior is:
LoaderComponent
when navigating to a route without any resolverI have added some logs on the NavigationStart
and NavigationEnd
events and I found that NavigationEnd
is triggered immediately after NavigationStart
(which is normal), while Overlay disappears about 0.5s after.
I have read the CHANGELOG.md
but I found nothing that might explain this problem. Any idea is welcome.
Edit:
After further research, I have restored the previous behavior by setting package.json
like this:
"@angular/cdk": "~7.0.0", "@angular/material": "~7.0.0",
instead of this:
"@angular/cdk": "~7.2.0", "@angular/material": "~7.2.0",
I have identified the faulty commit which has been released in version 7.1.0 and I posted my problem on the related GitHub issue. It fixes the fade out animation of the Overlay
.
What is the v7.1+ compliant way to get the desired behavior? According to me, the best thing to do would be: show the loader only when necessary, but NavigationStart
doesn't hold the needed information. I'd like to avoid ending up with some debounce behavior.
Angular loader allows your angular scripts to be loaded in any order. As angular-seed project shows us, Angular loader does not have any specific api, you just put it at the top of your index file (so that it's executed first) and then proceed to load your application files anyway you prefer.
Here is what I ended up with, after realizing that a delay
was a good solution in terms of UX because it allowed the loader to show only when the loading time is worth displaying a loader.
I don't like this solution because it implies to share a state between two Observables, when Observables are about pure pipes rather than side effects and shared states.
counter = 0; router.events.pipe( filter(x => x instanceof NavigationStart), delay(200), ).subscribe(() => { /* If this condition is true, then the event corresponding to the end of this NavigationStart has not passed yet so we show the loader */ if (this.counter === 0) { loaderService.show(); } this.counter++; }); router.events.pipe( filter(x => x instanceof NavigationEnd || x instanceof NavigationCancel || x instanceof NavigationError) ).subscribe(() => { this.counter--; loaderService.hide(); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With