When faced with such cases, this is my usual approach:
1. I start by creating a Resolver service that implements the Resolve
interface. This service ensures that all necessary data is retrieved before activating the route:
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
import { DataService } from 'path/to/data.service';
@Injectable()
export class ExampleResolverService implements Resolve<any> {
constructor(private _dataService: DataService) { }
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<any> {
return this._dataService.anyAsyncCall()
.then(response => {
/* Assume the method returns a response with a field "result" that can be either "true" or "false" */
/* "setResult" simply stores the passed argument in the "DataService" class property */
this._dataService.setResult(response.result);
})
.catch(err => this._dataService.setResult(false););
}
}
2. Next, let's consider how to handle the AuthGuard, which implements the CanActivate
interface:
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { DataService } from 'path/to/data.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private _dataService: DataService) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
/* The "getResult" method works with the same class property as setResult, but it only returns its value */
return this._dataService.getResult(); // will return either "true" or "false"
}
}
3. Finally, incorporate the Resolver and AuthGuard into your routes configuration. Here is an example structure (the actual route setup may vary, but this provides a basis for including the parent component activation):
const routes: Routes = [
{
path: 'app',
component: AppComponent,
resolve: {
result: ExampleResolverService // your resolver
},
canActivate: [AuthGuard], // your AuthGuard with "canActivate" method
children: [...] // child routes are defined within this array
}
];
Functionality Overview
Upon navigating to /app
, the ExampleResolverService
initiates, executes the API call, and saves the required part of the response in a class property within DataService
using the setResult
method (a standard setter operation). Subsequently, the AuthGuard
comes into play after the completion of the resolver task. It retrieves the stored result from DataService
through the getResult
method (a traditional getter), and subsequently returns this boolean result (since the AuthGuard
expects a boolean outcome for activation – returning true
activates the route while false
prevents activation).
This example offers a basic framework without extra data manipulations. Typically, the logic is more intricate, but this foundation should suffice for fundamental comprehension.