Route Configuration
Route configuration defines the mapping between URL paths and components in your Angular application. Routes are defined using the Routes type and Route interface.
Import
import { Routes , Route } from '@angular/router' ;
Routes Type
An array of Route objects that defines the routing configuration for the application.
Route Interface
interface Route {
// Path Configuration
path ?: string ;
pathMatch ?: 'prefix' | 'full' ;
matcher ?: UrlMatcher ;
// Component Configuration
component ?: Type < any >;
loadComponent ?: () => Promise < Type < any >>;
redirectTo ?: string | RedirectFunction ;
// Child Routes
children ?: Routes ;
loadChildren ?: LoadChildren ;
// Named Outlets
outlet ?: string ;
// Guards
canActivate ?: Array < CanActivateFn | DeprecatedGuard >;
canActivateChild ?: Array < CanActivateChildFn | DeprecatedGuard >;
canDeactivate ?: Array < CanDeactivateFn < any > | DeprecatedGuard >;
canMatch ?: Array < CanMatchFn | DeprecatedGuard >;
canLoad ?: Array < CanLoadFn | DeprecatedGuard >; // deprecated
// Data and Resolution
data ?: Data ;
resolve ?: ResolveData ;
title ?: string | Type < Resolve < string >> | ResolveFn < string >;
// Additional Options
runGuardsAndResolvers ?: RunGuardsAndResolvers ;
providers ?: Array < Provider | EnvironmentProviders >;
}
Route Properties
Path Configuration
path
The URL path to match. Supports:
Static paths: 'home', 'about'
Dynamic parameters: 'users/:id', 'posts/:postId/comments/:commentId'
Wildcard: '**' (matches any URL)
Empty path: '' (matches without consuming URL segments)
Examples:
const routes : Routes = [
{ path: 'home' , component: HomeComponent },
{ path: 'users/:id' , component: UserComponent },
{ path: 'products/:category/:productId' , component: ProductComponent },
{ path: '' , redirectTo: '/home' , pathMatch: 'full' },
{ path: '**' , component: NotFoundComponent }
];
pathMatch
pathMatch ?: 'prefix' | 'full'
The path matching strategy:
'prefix' (default): Matches when the URL starts with the path
'full': Matches only when the URL exactly matches the path
Example:
const routes : Routes = [
// Must match exact empty path for redirect
{ path: '' , pathMatch: 'full' , redirectTo: '/home' },
// Prefix match allows child routes
{ path: 'admin' , component: AdminComponent , children: [ ... ] }
];
Always use pathMatch: 'full' when redirecting from an empty path, otherwise the redirect will apply to all URLs.
matcher
A custom function for URL matching. Cannot be used with path.
Type Definition:
type UrlMatcher = (
segments : UrlSegment [],
group : UrlSegmentGroup ,
route : Route
) => UrlMatchResult | null ;
type UrlMatchResult = {
consumed : UrlSegment [];
posParams ?: { [ name : string ] : UrlSegment };
};
Example:
import { UrlSegment } from '@angular/router' ;
// Match URLs ending with .html
export function htmlFilesMatcher ( segments : UrlSegment []) {
return segments . length === 1 && segments [ 0 ]. path . endsWith ( '.html' )
? { consumed: segments }
: null ;
}
const routes : Routes = [
{ matcher: htmlFilesMatcher , component: HtmlViewerComponent }
];
Component Configuration
component
The component to instantiate when the path matches.
Example:
const routes : Routes = [
{ path: 'home' , component: HomeComponent },
{ path: 'users/:id' , component: UserDetailComponent }
];
loadComponent
loadComponent ?: () => Promise < Type < any > | DefaultExport < Type < any >>>
Lazy-load a standalone component.
Examples:
const routes : Routes = [
{
path: 'admin' ,
loadComponent : () => import ( './admin/admin.component' ). then ( m => m . AdminComponent )
},
// With default export, .then() can be omitted
{
path: 'profile' ,
loadComponent : () => import ( './profile/profile.component' )
}
];
redirectTo
redirectTo ?: string | RedirectFunction
URL to redirect to when this path matches. Can be:
Absolute path: '/home'
Relative path: '../other'
Path with parameters: '/users/:id'
Function for conditional redirects: RedirectFunction
Examples:
const routes : Routes = [
// Simple redirect
{ path: '' , redirectTo: '/home' , pathMatch: 'full' },
// Redirect with parameters
{ path: 'old-users/:id' , redirectTo: '/users/:id' },
// Conditional redirect function
{
path: 'dashboard' ,
redirectTo : ( route ) => {
const userService = inject ( UserService );
return userService . isAdmin () ? '/admin-dashboard' : '/user-dashboard' ;
}
}
];
Child Routes
children
Nested child routes.
Example:
const routes : Routes = [
{
path: 'products' ,
component: ProductsComponent ,
children: [
{ path: '' , component: ProductListComponent },
{ path: ':id' , component: ProductDetailComponent },
{ path: ':id/edit' , component: ProductEditComponent }
]
}
];
Template for parent component:
< h1 > Products </ h1 >
< router-outlet ></ router-outlet >
loadChildren
loadChildren ?: LoadChildren
Lazy-load child routes.
Type Definition:
type LoadChildren = () =>
| Routes
| Type < any >
| Observable < Routes | Type < any >>
| Promise < Routes | Type < any > | DefaultExport < Routes | Type < any >>>;
Examples:
const routes : Routes = [
// Lazy load routes
{
path: 'admin' ,
loadChildren : () => import ( './admin/admin.routes' ). then ( m => m . ADMIN_ROUTES )
},
// Lazy load NgModule (legacy)
{
path: 'legacy' ,
loadChildren : () => import ( './legacy/legacy.module' ). then ( m => m . LegacyModule )
},
// With default export
{
path: 'dashboard' ,
loadChildren : () => import ( './dashboard/routes' )
}
];
Named Outlets
outlet
Name of the RouterOutlet where the component should be rendered.
Example:
const routes : Routes = [
{ path: 'home' , component: HomeComponent },
{ path: 'sidebar' , component: SidebarComponent , outlet: 'side' },
{ path: 'popup' , component: PopupComponent , outlet: 'popup' }
];
Template:
< router-outlet ></ router-outlet > <!-- primary outlet -->
< router-outlet name = "side" ></ router-outlet >
< router-outlet name = "popup" ></ router-outlet >
Navigate to named outlet:
router . navigate ([{
outlets: {
primary: 'home' ,
side: 'sidebar' ,
popup: 'popup'
}
}]);
Guards
canActivate
canActivate ?: Array < CanActivateFn | DeprecatedGuard >
Guards that determine if the route can be activated.
Example:
import { inject } from '@angular/core' ;
import { CanActivateFn , Router } from '@angular/router' ;
import { AuthService } from './auth.service' ;
export const authGuard : CanActivateFn = ( route , state ) => {
const authService = inject ( AuthService );
const router = inject ( Router );
if ( authService . isLoggedIn ()) {
return true ;
}
return router . createUrlTree ([ '/login' ], {
queryParams: { returnUrl: state . url }
});
};
const routes : Routes = [
{
path: 'admin' ,
component: AdminComponent ,
canActivate: [ authGuard ]
}
];
canActivateChild
canActivateChild ?: Array < CanActivateChildFn | DeprecatedGuard >
Guards that determine if child routes can be activated.
Example:
const routes : Routes = [
{
path: 'admin' ,
component: AdminComponent ,
canActivateChild: [ adminGuard ],
children: [
{ path: 'users' , component: UsersComponent },
{ path: 'settings' , component: SettingsComponent }
]
}
];
canDeactivate
canDeactivate ?: Array < CanDeactivateFn < any > | DeprecatedGuard >
Guards that determine if the route can be deactivated (e.g., unsaved changes).
Example:
import { CanDeactivateFn } from '@angular/router' ;
export interface CanComponentDeactivate {
canDeactivate : () => boolean | Promise < boolean >;
}
export const unsavedChangesGuard : CanDeactivateFn < CanComponentDeactivate > = (
component
) => {
return component . canDeactivate ? component . canDeactivate () : true ;
};
const routes : Routes = [
{
path: 'edit' ,
component: EditComponent ,
canDeactivate: [ unsavedChangesGuard ]
}
];
canMatch
canMatch ?: Array < CanMatchFn | DeprecatedGuard >
Guards that determine if the route configuration can be matched.
Example:
import { inject } from '@angular/core' ;
import { CanMatchFn } from '@angular/router' ;
import { FeatureFlagService } from './feature-flag.service' ;
export const featureGuard : CanMatchFn = ( route ) => {
const featureFlags = inject ( FeatureFlagService );
const requiredFeature = route . data ?.[ 'feature' ];
return featureFlags . isEnabled ( requiredFeature );
};
const routes : Routes = [
{
path: 'beta-feature' ,
component: BetaComponent ,
canMatch: [ featureGuard ],
data: { feature: 'beta-feature' }
},
// Fallback if feature not enabled
{ path: 'beta-feature' , component: ComingSoonComponent }
];
Data and Resolution
data
Static data associated with the route.
Type:
type Data = { [ key : string | symbol ] : any };
Example:
const routes : Routes = [
{
path: 'products' ,
component: ProductsComponent ,
data: { title: 'Products' , breadcrumb: 'All Products' , roles: [ 'user' , 'admin' ] }
}
];
// Access in component
import { Component , inject , OnInit } from '@angular/core' ;
import { ActivatedRoute } from '@angular/router' ;
@ Component ({ /* ... */ })
export class ProductsComponent implements OnInit {
private route = inject ( ActivatedRoute );
ngOnInit () {
const data = this . route . snapshot . data ;
console . log ( data [ 'title' ]); // 'Products'
}
}
resolve
Data resolvers that pre-fetch data before route activation.
Type:
type ResolveData = {
[ key : string ] : ResolveFn < any > | DeprecatedResolve ;
};
type ResolveFn < T > = (
route : ActivatedRouteSnapshot ,
state : RouterStateSnapshot
) => MaybeAsync < T | RedirectCommand >;
Example:
import { inject } from '@angular/core' ;
import { ResolveFn } from '@angular/router' ;
import { UserService , User } from './user.service' ;
export const userResolver : ResolveFn < User > = ( route ) => {
const userService = inject ( UserService );
return userService . getUser ( route . params [ 'id' ]);
};
const routes : Routes = [
{
path: 'users/:id' ,
component: UserDetailComponent ,
resolve: { user: userResolver }
}
];
// Access resolved data in component
@ Component ({ /* ... */ })
export class UserDetailComponent implements OnInit {
private route = inject ( ActivatedRoute );
ngOnInit () {
const user = this . route . snapshot . data [ 'user' ];
console . log ( user );
}
}
title
title ?: string | Type < Resolve < string >> | ResolveFn < string >
Page title for the route.
Examples:
const routes : Routes = [
// Static title
{ path: 'home' , component: HomeComponent , title: 'Home' },
// Dynamic title with resolver
{
path: 'users/:id' ,
component: UserComponent ,
title : ( route ) => `User ${ route . params [ 'id' ] } `
}
];
Additional Options
runGuardsAndResolvers
runGuardsAndResolvers ?: RunGuardsAndResolvers
Defines when guards and resolvers should run.
Type:
type RunGuardsAndResolvers =
| 'pathParamsChange'
| 'pathParamsOrQueryParamsChange'
| 'paramsChange'
| 'paramsOrQueryParamsChange'
| 'always'
| (( from : ActivatedRouteSnapshot , to : ActivatedRouteSnapshot ) => boolean );
Example:
const routes : Routes = [
{
path: 'search' ,
component: SearchComponent ,
runGuardsAndResolvers: 'paramsOrQueryParamsChange' ,
resolve: { results: searchResolver }
}
];
providers
providers ?: Array < Provider | EnvironmentProviders >
Dependency injection providers for this route and its children.
Example:
import { Routes } from '@angular/router' ;
import { UserService } from './user.service' ;
const routes : Routes = [
{
path: 'admin' ,
component: AdminComponent ,
providers: [ UserService ],
children: [
// Child routes can inject UserService
{ path: 'users' , component: UsersComponent }
]
}
];
Common Route Patterns
Basic Routes
const routes : Routes = [
{ path: '' , redirectTo: '/home' , pathMatch: 'full' },
{ path: 'home' , component: HomeComponent },
{ path: 'about' , component: AboutComponent },
{ path: 'contact' , component: ContactComponent },
{ path: '**' , component: NotFoundComponent }
];
Parameterized Routes
const routes : Routes = [
{ path: 'users/:id' , component: UserDetailComponent },
{ path: 'posts/:postId/comments/:commentId' , component: CommentComponent },
{ path: 'products/:category' , component: ProductListComponent }
];
Nested Routes
const routes : Routes = [
{
path: 'dashboard' ,
component: DashboardComponent ,
children: [
{ path: '' , component: DashboardHomeComponent },
{ path: 'stats' , component: StatsComponent },
{ path: 'reports' , component: ReportsComponent }
]
}
];
Lazy Loading
const routes : Routes = [
{
path: 'admin' ,
loadChildren : () => import ( './admin/admin.routes' ). then ( m => m . ADMIN_ROUTES ),
canMatch: [ adminGuard ]
},
{
path: 'profile' ,
loadComponent : () => import ( './profile/profile.component' ),
canActivate: [ authGuard ]
}
];
Protected Routes
const routes : Routes = [
{
path: 'admin' ,
component: AdminLayoutComponent ,
canActivate: [ authGuard , adminGuard ],
canActivateChild: [ adminGuard ],
children: [
{ path: 'users' , component: UsersComponent },
{ path: 'settings' , component: SettingsComponent }
]
}
];
Routes with Resolvers
const routes : Routes = [
{
path: 'product/:id' ,
component: ProductComponent ,
resolve: {
product: productResolver ,
reviews: reviewsResolver
}
}
];
See Also
Router Class Router service API
Route Guards Guard functions and interfaces
Routing Guide Complete routing guide
Lazy Loading Lazy loading feature modules