New in Angular 7.1: Router Updates
In this article, we’ll explore how to start using these new features. We’ll also understand the motivations behind them, and take a glance at how they are implemented in the Angular sources.

New in Angular 7.1: Router Updates
In this article, we’ll explore how to start using these new features. We’ll also understand the motivations behind them, and take a glance at how they are implemented in the Angular sources.


Some new features have been added to the Angular Router with version 7.1.0:
- Router guards can now return a
UrlTree
. This allows a guard to cancel the current navigation and redirect to the URL represented by theUrlTree
. - There is now a notion of “guard priority”, which is used as a tie-breaker when multiple guards return a
UrlTree
during a single navigation. - A new configuration option for
runGuardsAndResolvers
calledpathParamsChange
has been added.
In this article, we’ll explore how to start using these new features. We’ll also understand the motivations behind them, and take a glance at how they are implemented in the Angular sources.
Jason Aden covered many of these topics in his excellent talk at AngularConnect 2018, so please be sure to check that out as well. The router portion of his talk starts here.
Perform Navigation/Redirects from Guards by returning a UrlTreeLink to this section
MotivationLink to this section
Prior to this change, when multiple guards were executed during navigation, it was possible for each of them to start a navigation by calling navigateByUrl
. In such scenarios, it was unclear as to which guard’s navigation should win.
With this change, the guard with the highest priority that returns a UrlTree
will cancel the current navigation, and a redirect will be made to the URL represented by the returned UrlTree
.
We’ll see what “highest priority” means shortly.
BackgroundLink to this section
Before digging into this change, it’s worth understanding the differences between a URL and a UrlTree.
Inside the Angular Router, a URL string is represented using a structure called a UrlTree
. It’s easy to convert a string URL into a UrlTree using the parseUrl
method of the Router
service:
<>Copyconst url = 'target'; const tree: UrlTree = this.router.parseUrl(url);


If you’d like to know more about the relationship between URLs and UrlTrees in Angular, I’ve written about them in-depth in this article.
The ChangeLink to this section
Prior to this change, Router guards could only return boolean
values. A return value of true
meant the navigation could proceed, and a return value of false
would cancel the navigation.
Now, for CanActivate
, CanActivateChild
, and CanDeactivate
, there is a third option; these guards can return a UrlTree
directly. In these scenarios, the current navigation is cancelled, and a new navigation is created, which routes to the path specified by the returned UrlTree
. For example, if a user fails an authentication guard, you may want to redirect that user directly to the login page.
ExampleLink to this section
This example application has two routes:
<>Copyconst ROUTES: Route[] = [ { path: 'target', component: TargetComponent }, { path: 'redir', component: NeverGetHereComponent, canActivate: [CanActivateRouteGuard] } ];
We’ll make it so that /redir
always redirects to /target
instead of displaying NeverGetHereComponent
. Rather than using redirectTo: 'target'
inside of the Route definition for path: 'redir'
, we’ll let the CanActivateRouteGuard
initiate the redirect instead.
We’ll start with an ordinary guard function, and modify its canActivate
method to return a UrlTree
instead of a Boolean value:
<>Copyimport { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree } from '@angular/router'; @Injectable() export class CanActivateRouteGuard implements CanActivate { constructor(private router: Router) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree { const url = 'target'; const tree: UrlTree = this.router.parseUrl(url); return tree; } }
As previously mentioned, parseUrl
is a function from the Router service. It takes a URL encoded as a string and transforms it into a UrlTree
.
Our guard is ready, so we’ll attach it to the { path: 'redir' ... }
route.
<>Copy{ path: 'redir', component: NeverGetHereComponent, canActivate:[CanActivateRouteGuard] }
Now, whenever we route to /redir, the navigation will proceed as normal until it checks the guards. When our guard function returns a UrlTree pointing to target, the navigation to redir will be cancelled, and a new navigation will begin, targeting target. We can confirm this by clicking the redirect link in Stackblitz:


and then checking the browser console:


That’s all it takes to set up redirects from route guards!
Guard Priority
We frequently have multiple guards protecting a route. You may be wondering what happens when multiple guards try to perform a redirect during a navigation. What if several of these guards return UrlTrees?
With Angular 7.1.0, there is a notion of guard priority. Guard priority is implemented internally via a custom RxJS operator called prioritizedGuardValue. We won’t get into the implementation details here, but this operator will make sure that the guard with the highest priority wins whenever multiple guards return UrlTrees.
Consider the following example:
<>Copy{ path: 'redir', canActivate: [CanActivateRouteGuard, CanActivateRouteGuard2], children: [{ path: 'dir', component: NeverGetHereComponent, canActivate: [ChildCanActivateRouteGuard] }] }
Here is how guard priority is calculated for multiple canActivate
guards:
- The current route's
canActivate
guards are processed before any of its children’scanActivate
guards. - Within a
canActivate
array, the guard at index 0 has the highest priority, followed by the guard at index 1, and so on.
Another way of thinking about canActivate
is that the guard closest to the root of the application has the highest priority. So in the above snippet, CanActivateRouteGuard
has the highest priority, followed by CanActivateRouteGuard2
, and then ChildCanActivateRouteGuard
.
All guards in a given canActivate
array are executed in parallel, but the router will wait until any guards with a higher priority to finish before moving on. So in the above example:
- Even if
CanActivateRouteGuard2
returns aUrlTree
immediately:
the router will still wait forCanActivateRouteGuard
to resolve before initiating a new navigation. - If
CanActivateRouteGuard
returns aUrlTree
:
that will win. - If it returns
false
:
the entire navigation fails (and no redirects happen). - If it simply returns
true
:
then the UrlTree returned byCanActivateRouteGuard2
will be navigated to.
You can see how different scenarios play out by looking at the tests for the prioritizedGuardValue operator.
You can also experiment at this stackblitz. I recommend going into the three guards, and changing their delays and return values, as well as their order in the canActivate
array in app.module.ts
.
runGuardsAndResolvers has a new option: pathParamsChangeLink to this section
The official documentation describes the runGuardsAndResolvers
option as:
defines when guards and resolvers will be run. By default they run only when the matrix parameters of the route change. When set to paramsOrQueryParamsChange
they will also run when query params change. And when set to always
, they will run every time.
With the new pathParamsChange
option, guards and resolver functions will run only if the path or path parameters change. Changes to any other types of parameters, such as matrix parameters or query parameters, will not cause the guards and resolvers to run.
MotivationLink to this section
As is described in the sources:
`pathParamsChange` Run guards and resolvers path or any path params change. This mode is * useful if you want to ignore changes to all optional parameters such as query *and* matrix * params.
Usage exampleLink to this section
runGuardsAndResolvers
is a property of Routes, so it is used in a route configuration:
<>Copy{ path: '...', runGuardsAndResolvers: 'pathParamsChange'}
SummaryLink to this section
With the release of Angular 7.1.0, Route Guard functions now have the option of returning a UrlTree
to cancel the current navigation and redirect to a route.
To initiate a redirect from a guard function, do the following:
- Create a guard function which uses
parseUrl
to return a UrlTree - Register the guard with a route, as normal
There is also a new option for specifying when to run resolvers and guard functions, called pathParamsChange
, which is useful when you only want to run guards and resolvers on essential navigations and ignore any optional parameters, like matrix or query params.
Comments (0)
Be the first to leave a comment
About the author

Fullstack Developer. Love digging into the internals of stuff. Always trying to reach the next level.

About the author
Nate Lapinski
Fullstack Developer. Love digging into the internals of stuff. Always trying to reach the next level.
About the author

Fullstack Developer. Love digging into the internals of stuff. Always trying to reach the next level.