DEV Community

Connie Leung
Connie Leung

Posted on • Edited on • Originally published at blueskyconnie.com

5

Asynchronous redirectTo function in Angular Routing

One of the new features in Angular 20.0.0-next.8 is the asynchronous redirect function. The redirect function redirects from a matched route path to another in the routing configuration. In version 19, the function's return type is string | UrlTree, which is a synchronous value. This feature allows the function to return an Observable or a Promise, which may be useful in some use cases.

The Problem It Solves

A static redirected route is sufficient in most cases. However, some scenarios may require the redirect function to make backend requests to obtain the routes based on dynamic criteria. The code changes allow the function to inject an HttpClient or use the fetch function to retrieve the value. The result is either an Observable or a Promise. Do not worry; the function continues to support string and UrlTree in v20.

First, let's update Angular to the latest version 20. As of this writing, the Angular version is 20.0.0-next.9.

ng update @angular/core @angular/cli --next
Enter fullscreen mode Exit fullscreen mode

In this demo, we will create some Pokemon routes that redirect to a general route to retrieve Pokemon details by name. Some redirected routes are Observables and some are Promises. For example, /pikachu will be redirected to Observable('/pokemon/pikachu') and /bulbasaur will be redirected to Promise.resolve('/pokemon/bulbasaur'). In real-world applications, they should be static strings, but they are returned as asynchronous values for demo purposes.

Defining the App Configuration

export const appConfig: ApplicationConfig = {
 providers: [
   provideBrowserGlobalErrorListeners(),
   provideZonelessChangeDetection(),
   provideRouter(routes, withComponentInputBinding()),
   provideHttpClient(),
 ]
};
Enter fullscreen mode Exit fullscreen mode

The application provides HttpClient to make backend requests to retrieve Pokemon details and routes to redirect to a Pokemon component to display the details.

Application Routes

Here are the routes of the application.

export const LINKS = [
   {
       path: 'pikachu',
       label: 'Pikachu'
   },
   {
       path: 'bulbasaur',
       label: 'Bulbasaur'
   },
];

const pokemonRoutes: Routes = LINKS.map(({ path, label: title }, i) => {
   const route = `/pokemon/${path}`;
   return {
       path,
       title,
       redirectTo: () => i % 2 === 0 ? of(route) : Promise.resolve(route)
   }
});
Enter fullscreen mode Exit fullscreen mode

I made the pokemonRoutes to return an Observable for path pikachu and a Promise for path bulbasaur for demo reasons.

export const routes: Routes = [
   {
       path: 'home',
       loadComponent: () => import('./home/home.component'),
   },
   ...pokemonRoutes,
   {
       path: 'pokemon/:id',
       resolve:{
           pokemon:   preload Pokemon to make the component feel faster after navigation  
       },
       loadComponent: () => import('./pokemon/pokemon.component'),
   },
    other routes
];
Enter fullscreen mode Exit fullscreen mode

The routes array included pikachu, bulbasaur and pokemon/:id. The pokemon/:id route preloads data so that the Pokemon details are available to the pokemon input of the Pokemon component.
Display Route Links on Navigation Bar of App Component.

I created a NavBarComponent to render the routerLink.

<header>
   <p>{{ `${version} - ${name}` }}</p>
   <div class="links">
       @for (link of links; track link.path) {
           <a [routerLink]="link.path">{{ link.label }}</a>
       }
   </div>
</header>
Enter fullscreen mode Exit fullscreen mode
@Component({
 selector: 'app-nav-bar',
 imports: [RouterLink],
 templateUrl: './nav-bar.component.html',
 styleUrl: './nav-bar.component.scss',
 changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NavBarComponent {
 version = VERSION.full;
 name = 'Asynchronous Redirect Demo';
 links = LINKS;
}
Enter fullscreen mode Exit fullscreen mode

When these links are clicked, they are redirected to /pokemon/:id and the pokemon component is loaded lazily to display the details. The behavior of redirect remains the same for synchronous and asynchronous values.

<div class="page-grid">
   <app-nav-bar class="navbar" />
   <div class="router-content">
       <router-outlet />
   </div>
</div>
Enter fullscreen mode Exit fullscreen mode
@Component({
 selector: 'app-root',
 imports: [RouterOutlet, NavBarComponent],
 templateUrl: './app.component.html',
 styleUrl: './app.component.scss',
 changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {}
Enter fullscreen mode Exit fullscreen mode

In this code, the AppComponen serves as the root component of the Angular application. Its primary responsibility is to integrate and render the NavBarComponent.

Conclusion

When a path requires redirection, we can assign a function to the redirectTo property to redirect to the expected route. The function can return a string, an UrlTree, an Observable<string | UrlTree> or a Promise<string | UrlTree>. It is feasible to request an API to obtain data, construct the dynamic route, and return an Observable or Promise of the dynamic route.

Resources

AWS Security LIVE! Stream

Streaming live from AWS re:Inforce

Tune into Security LIVE! at re:Inforce for expert takes on modern security challenges.

Learn More

Top comments (4)

Collapse
 
dzhavat profile image
Dzhavat Ushev

Super nice post! That's exactly what I need now ... but will have to wait until v20 is released ... and we upgrade to it. 😬

Since the redirectTo does not support async now, what is our next best solution? A guard that redirects to the desired route?

Collapse
 
railsstudent profile image
Connie Leung

Probably do the redirect inside a component based on your criteria. In ngOnInit or constructor of component, call navigateTo or navigateByUrl to navigate to the destination.

Collapse
 
dzhavat profile image
Dzhavat Ushev

Thanks for the reply. I went with the route guard approach. A route that is redirected to has a guard that checks whether the user needs to be redirected to another route. It seems to be working. And it's also a temporary solution until we upgrade to v20.

So something like this.

/reports
    "" (empty route, redirects to "report-a"
    report-a (async guard checks if the user is allowed, if not - redirect to another "report-*" route, or "root")
    report-b
    report-c
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
railsstudent profile image
Connie Leung

Thanks. I need to check on route guard. Thank you for teaching me.

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →

AWS Security LIVE! From re:Inforce 2025

Tune into AWS Security LIVE! streaming live from the AWS re:Inforce expo floor in Philadelphia from 8:00AM ET-6:00PM ET.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️