DEV Community

Cover image for Explore Angular Router's  runGuardsAndResolvers
Juri Strumpflohner for Angular

Posted on • Originally published at juristr.com

Explore Angular Router's runGuardsAndResolvers

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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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'
  }
])

Enter fullscreen mode Exit fullscreen mode

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.

New Modes in Ang...

Read more Β»

Discussion (2)

Collapse
maxime1992 profile image
Maxime

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

Collapse
juristr profile image
Juri Strumpflohner Author

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