Learn how we can use new options introduced for the runGuardsAndResolvers
setting for the Angular Router configuration to get a better control over when to run our resolvers and guards.
I'm pretty sure you know about Router guards and resolvers and what they are good for. If not, don't worry. I have a full course out on Egghead.io ๐.
The runGuardsAndResolvers
options (here's the official doc) is actually quite a hidden functionality and not that much used. However, it has been there already since about Angular v4. The possibilities at that time were quite limited though, something like the following:
// packages/router/src/router.ts (Angular v4)
private shouldRunGuardsAndResolvers(
curr: ActivatedRouteSnapshot, future: ActivatedRouteSnapshot,
mode: RunGuardsAndResolvers): boolean {
switch (mode) {
case 'always':
return true;
case 'paramsOrQueryParamsChange':
return !equalParamsAndUrlSegments(curr, future) ||
!shallowEqual(curr.queryParams, future.queryParams);
case 'paramsChange':
default:
return !equalParamsAndUrlSegments(curr, future);
}
}
Basically there were three options, always
, paramsOrQueryParamsChange
and paramsChange
. Given a route configuration, we can set a property runGuardsAndResolvers
and set it accordingly to one of those two options.
RouterModule.forRoot([
...
{
path: 'home/:id',
component: HomeComponent,
...
runGuardsAndResolvers: 'paramsChange'
}
])
By default if you don't specify any mode, the router will apply what is called paramsChange
mode, meaning it will re-run the guards and resolvers whenever the path or path params change. Examples of URLs satisfying this condition and hence execute the guards & resolvers would be the following:
-
/home/1
=>/home/2
-
/home/1
=>/home/1;param1=38
-
/home/1;param1=38
=>/home/1;param1=20
Examples not firing a change
-
/home/1
=>/home/1?queryParam=hi
- ...
On the other side, when setting it to paramsOrQueryParamsChange
the guards and resolvers fire on most changes to the URL and is just very similar to the always
option (the only difference being probably URL fragment changes):
-
/home/1
=>/home/2
-
/home/1
=>/home/1;param1=38
-
/home/1;param1=38
=>/home/1;param1=20
-
/home/1
=>/home/1?queryParam=hi
Basically as the name suggests, it fires whenever the params (i.e. ;param1=..
) changes or a query param (i.e. ?someQuery=..
). One might not guess, but it also changes for al modifications of the path, like in the very first example when moving from /home/1
to /home/2
.
Top comments (2)
That's cool for guards, but on the resolver part I don't understand why you'd ever use a resolver that's blocking the UI while it's fetching data. I know it's the whole point but from a user perspective having potentially huge lags whenever you go to a component using a resolver sounds like a bad experience ๐ค
I've raised a stackoverflow question and no one could come up with a proper answer why you'd ever want to use them stackoverflow.com/q/49054232/2398593
Using ngrx for ex, you can do the same with effects in a non blocking way which is way nicer ๐.
Do you often user resolvers Juri? If so can you give some more context about how and why? Thanks
Hey Maxime. I totally agree. I've rarely used resolvers, especially not to block the transition, maybe just to kick of the loading which will then be picked up by the component.
I mostly just transition to the component which then takes care of loading the data, and in case show a ghost element in between or something. Everything else usually hurts the user experience as you said