To achieve this functionality, I utilized a CanActivate guard. The crucial aspect of making it effective is to return an Observable from the canActivate method. This allows for the flexibility of delaying the navigation process as needed.
import { CanActivate } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { StateService } from '../../_services/state.service';
import { Subject } from 'rxjs/Rx';
import { Subscription } from 'rxjs/Subscription';
@Injectable()
export class LoadingGuard implements CanActivate {
constructor(private state: StateService) {}
public canActivate(): Observable<boolean> {
if (!this.state.loading$.getValue()) {
return Observable.of(true);
}
let subject = new Subject<boolean>();
let subscription = this.state.loading$.subscribe(value => {
if (!value) {
subject.next(true);
subject.complete();
subscription.unsubscribe();
}
});
return subject;
}
}
The StateService mentioned above is responsible for evaluating the current user and pre-caching essential data for the application. It contains a subject named loading$
that signals when the loading process is complete.
Lastly, remember to add the guard to the app module.
import { LoadingGuard } from './app/loading-guard/loading-guard';
// other imports omitted
@NgModule({
// other module properties omitted
providers: [LoadingGuard]
})
export class AppModule {}
Then incorporate the guard into your routing configuration.
import { LoadingGuard } from './app/loading-guard/loading-guard';
// other imports omitted
export const rootRouterConfig: Routes = [
{ path: 'app', component: AppComponent,
canActivate: [LoadingGuard],
children: [
{ path: 'index', component: IndexComponent },
// child routes omitted
] },
{ path: 'sign-in', component: SignInComponent },
{ path: '**', redirectTo: 'sign-in' }
];
For further information, refer to the official documentation on CanActivate:
https://angular.io/docs/ts/latest/api/router/index/CanActivate-interface.html