Navigating Angular Apps: A Guide to RedirectCommand
Since Angular introduced the capability to return a UrlTree
in router guards, it has become a preferred method for implementing redirects due to its ability to offer a smoother redirecting experience. However, it's essential to note that it doesn't completely replace the functionality of the traditional router.navigate(...); return false;
pattern.
Here are two common scenarios where this technique is particularly useful:
- Redirecting to a 404 Page for Unknown Resources: When attempting to access an unknown resource, it’s typical to redirect to a 404 page. The expected behavior here is akin to
skipLocationChange
, where users can see the URL of the unknown resource, allowing them to identify and correct any typos. However, with theUrlTree
technique, the URL displayed after the redirect shows/404
. - Performing a 301 Redirect to a Resource’s Canonical URL: In cases where a resource’s URL can be renamed or aliased, performing a 301 redirect to its canonical URL is beneficial. Ideally, this should behave like
replaceUrl
, where users see the canonical URL without the option to navigate back to the obsolete or aliased URL. Yet, with theUrlTree
technique, users can still navigate back to the obsolete or aliased URL.
In Angular 18, the introduction of the RedirectCommand
offers a solution to address these shortcomings by providing options similar to those available with router.navigate
. This allows for more fine-grained control over navigation behavior, including skipLocationChange
, replaceUrl
:
import { RedirectCommand } from '@angular/router';
export const routes: Routes = [
{
path: 'foo',
component: FooComponent,
canActivate: [
() => {
return new RedirectCommand(inject(Router).parseUrl('/error'), {
skipLocationChange: true,
});
},
],
},
{
path: 'error',
component: ErrorComponent,
},
];
With the use of RedirectCommand
, the redirect occurs without altering the browser's URL, while still rendering the ErrorComponent
.
RedirectCommand in Route Resolvers
Furthermore, this capability extends to router resolvers, offering more versatility in navigation handling:
export const routes: Routes = [
{
path: 'parent/:id',
component: BlankCmp,
resolve: {
redirectMe: () => {
return new RedirectCommand(inject(Router).parseUrl('/login')
}
},
},
{
path: 'login',
component: BlankCmp,
}
];
By returning a RedirectCommand
in resolvers, the router cancels the current navigation and redirects to the specified location. It's worth noting that if multiple resolvers return a RedirectCommand
, only the first one encountered during execution will be utilized.
Follow me on Medium or Twitter to read more about Angular and JS!