I have a situation where I've been using a Resolve to pre-load some data from a remote source via an HTTP call prior to navigating to a component. Now I need to implement some guard logic which requires that, depending on some conditions, that data be pre-loaded to verify some fields on it against the current user.
I'd like to avoid making the exact same request to the backend in the CanActivate
guard and then immediately afterwards in the Resolve
.
Is there some way I can access the route data from inside the CanActivate
or the route config to temporarily override the resolver and just set the value on the data object since I've got what I'm about to request?
I tried getting away with something as simple as
route.data['myData'] = value;
But this is an error because "object is not extensible".
I also tried something like:
this.router.routerState.root.data['myData'] = value;
Which didn't create any errors, however the data hadn't survived into the route.data
element of the Resolve.resolve()
method.
I'd like to avoid something too custom or hacky like temporarily storing the object on the Service like some sort of cache. Is there any standard mechanism for transferring data between internal router elements to support advanced pre-fetching and stuff like data ownership checks?
EDIT
The routerState does work if you inject the Router into the constructor of the Resolve
class, and access it the same way. But this needs to be cleared afterwards otherwise it does persist between navigation calls.
CanActivate is an interface used to check whether a route can be activated or not. Usually used to protect a web page from unauthorized access. And the data thrown on the canActive API is the roles parameter. Okay, follow this simple tutorial.
CanActivatelink Interface that a class can implement to be a guard deciding if a route can be activated. If all guards return true , navigation continues. If any guard returns false , navigation is cancelled.
CanActivate is an interface and shall used for authenticate the user and allow them conditionally access the route. CanActivate executes before Resolve. Resolve interface shall used to ensure the data available for the page to load. It executes after all the routes executed.
The canActivate method returns a boolean indicating whether or not navigation to a route should be allowed. If the user isn't authenticated, they are re-routed to some other place, in this case a route called /login . Now the guard can be applied to any routes you wish to protect.
The property data
of an ActivatedRouteSnapshot
is immutable, this is the reason why you receive the error:
object is not extensible
But you can replace the whole object, like that:
@Injectable()
export class MyGuard implements CanActivate {
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
// Use the spread operator to keep the previously resolved data
next.data = {...next.data, guardedData: 'guarded'};
return true;
}
}
And access it in your resolver
@Injectable()
export class FooResolver implements Resolve<any> {
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any>|Promise<any>|any {
return route.data.guardedData;
}
}
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