import { Injectable , InjectionToken , Inject } from '@angular/core' ; import { CanActivate , ActivatedRouteSnapshot } from '@angular/router' ; import { Observable , forkJoin , of } from 'rxjs' ; import { tap , map , catchError } from 'rxjs/operators' ; export type ExtensionLoaderCallback = ( route : ActivatedRouteSnapshot ) => Observable < boolean > ; export function DefaultExtensionLoaderFactory ( ) { return [ ] ; } export const EXTENSION_DATA_LOADERS = new InjectionToken < ExtensionLoaderCallback [ ] > ( 'EXTENSION_DATA_LOADERS' , { providedIn : 'root' , factory : DefaultExtensionLoaderFactory } ) ; @ Injectable ( { providedIn : 'root' } ) export class ExtensionsDataLoaderGuard implements CanActivate { private invoked = false ; constructor ( @ Inject ( EXTENSION_DATA_LOADERS ) private extensionDataLoaders ) { } canActivate ( route ) { if ( ! this . invoked ) { if ( ! this . extensionDataLoaders . length ) { this . invoked = true ; return of ( true ) ; } const dataLoaderCallbacks = this . extensionDataLoaders . map ( ( callback ) => callback ( route ) ) ; return forkJoin ( ... dataLoaderCallbacks ) . pipe ( map ( ( ) => true ) , tap ( ( ) => ( this . invoked = true ) ) , catchError ( ( e ) => { console . error ( 'Some of the extension data loader guards has been errored.' ) ; console . error ( e ) ; return of ( true ) ; } ) ) ; } else { return of ( true ) ; } } canActivateChild ( ) { return of ( true ) ; } }