Skip to content

Angular Routes

Route configuration objects support far more than a simple path-to-component mapping. This lesson covers redirects, lazy loading, static data, and resolvers.

What Belongs in a Route Configuration?

A route object can specify a component to render directly, a lazily loaded component or module, a redirect to another path, static data, and a resolve map for fetching data before the route activates.

Understanding each option lets you avoid unnecessary boilerplate, like manually redirecting in a component's ngOnInit when a redirectTo route would do the same thing declaratively.

export const routes: Routes = [
  { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
  {
    path: 'dashboard',
    loadComponent: () => import('./dashboard/dashboard.component').then(m => m.DashboardComponent),
    data: { title: 'Dashboard' },
  },
];

loadComponent lazily imports the component's file only when the route is actually navigated to, reducing the initial bundle size.

Route Configuration Options

{
  path: 'segment',
  component: SomeComponent,
  loadComponent: () => import('./x.component').then(m => m.X),
  loadChildren: () => import('./feature.routes'),
  redirectTo: '/other',
  pathMatch: 'full' | 'prefix',
  data: { key: 'value' },
  resolve: { user: userResolver },
}
  • loadComponent/loadChildren enable lazy loading, splitting that route into its own JavaScript chunk.
  • pathMatch: 'full' is required on empty-path redirects to avoid matching every route.
  • data attaches static metadata (like a page title) readable via ActivatedRoute.
  • resolve runs a function to fetch data before the route activates, so the component never renders without it.

Route Configuration Cheatsheet

The full range of options you can attach to a single route.

Option Example Purpose
Static component component: HomeComponent Eagerly loaded component
Lazy component loadComponent: () => import(...) Code-split, loaded on demand
Lazy children loadChildren: () => import('./x.routes') Lazily load a whole feature's routes
Redirect redirectTo: '/home' Send users to another path
Path matching pathMatch: 'full' Require an exact match before redirecting
Static data data: { title: 'Home' } Attach metadata read via ActivatedRoute
Resolver resolve: { user: userResolver } Fetch data before the route activates
Guard canActivate: [authGuard] Control whether navigation is allowed

Lazy Loading Components and Feature Routes

loadComponent lazily loads a single standalone component; loadChildren lazily loads an entire feature's route configuration, both split into separate JavaScript chunks fetched only when needed, reducing the initial page load size.

{
  path: 'settings',
  loadComponent: () => import('./settings/settings.component').then(m => m.SettingsComponent),
},
{
  path: 'admin',
  loadChildren: () => import('./admin/admin.routes').then(m => m.ADMIN_ROUTES),
}

Fetching Data Before Activation With Resolvers

A resolver runs before a route activates and returns data (often via an Observable or Promise) that becomes available on ActivatedRoute.data, avoiding a loading flicker inside the component itself.

export const userResolver: ResolveFn<User> = (route) => {
  const userService = inject(UserService);
  return userService.getUser(route.paramMap.get('id')!);
};

{ path: 'users/:id', component: UserDetailComponent, resolve: { user: userResolver } }

Reading Route Data in a Component

Both static data and resolved data are available through the injected ActivatedRoute, typically read as an Observable via .data or synchronously via .snapshot.data.

export class UserDetailComponent {
  private route = inject(ActivatedRoute);
  user$ = this.route.data.pipe(map(data => data['user']));
}

Common Mistakes

  • Omitting pathMatch: 'full' on an empty-path redirect, causing it to match and redirect every route unintentionally.
  • Fetching data manually in ngOnInit when a resolver would eliminate loading-state boilerplate entirely.
  • Not handling resolver errors, an unhandled rejected resolver can leave navigation stuck.
  • Overusing eager component for large features that would benefit from loadComponent/loadChildren lazy loading.

Key Takeaways

  • Route configuration supports redirects, lazy loading, static data, and resolvers beyond a simple component mapping.
  • loadComponent/loadChildren split routes into separate, on-demand JavaScript chunks.
  • Resolvers fetch data before a route activates, avoiding loading-state boilerplate in the component.
  • Both static and resolved route data are accessible through the injected ActivatedRoute.

Pro Tip

Use resolvers sparingly for critical data the page cannot render without; for everything else, prefer fetching inside the component with clear loading states, resolvers that fail or run slowly can block navigation entirely.