Routing is the core engine that transforms a collection of components into a cohesive application. It manages the user's journey through your site's content.
1The SPA Advantage
Traditional websites reload the entire page every time you click a link. This is slow and resets the application's state. In an Angular SPA, the main HTML page is loaded only once. The Router then intercepts URL changes and dynamically updates the DOM by adding or removing components. This results in a seamless, lightning-fast user experience that feels like a native mobile app.
3Step-by-Step Breakdown
Welcome to the world of SPAs! In Angular, we don't load new HTML files from a server. We just swap components in and out. This is called Routing.
Think of your app as a theater. The theater (shell) stays the same, but the actors (components) change on stage based on the URL.
The <router-outlet> is the most important tag. It's the placeholder where Angular renders the component associated with the current URL.
Checkpoint: What is the purpose of the <router-outlet> tag in Angular?
- βIt defines the navigation links
- βIt's a placeholder for the routed components
To move between views, we don't use <a href='...'>. That would trigger a full page reload! Instead, we use the 'routerLink' directive.
Using routerLink tells Angular to update the URL and swap the component WITHOUT reloading the browser. It's fast and smooth.
Checkpoint: Why do we use 'routerLink' instead of a standard 'href' in Angular?
- βIt applies special CSS styles
- βTo prevent a full page reload and maintain SPA state
This client-side navigation is what makes modern web apps feel like desktop applications. Ready to configure your routes?
Next, we'll learn how to map specific URLs to specific components in the Routing Module.
Level Up π
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Always Use `routerLink` Instead of a Click Handler That Calls `router.navigate`
`routerLink` renders a real `<a href>` under the hood, giving you a genuine, crawlable, screen-reader-friendly link that supports right-click 'open in new tab' and middle-click β a `(click)` handler on a `<div>` or `<span>` calling `router.navigate()` provides none of that.
2`<router-outlet>` Swaps Content Without Resetting Keyboard Focus or Scroll Position
Unlike a traditional page navigation, Angular's router doesn't automatically move focus to the new view or scroll to the top β for a genuinely accessible SPA, wire up both explicitly on each successful navigation.
SEO Implications
- 1
Real `<a routerLink>` Links Are What Let Crawlers Discover Your Routes at All
Search engine crawlers primarily discover pages by following `<a href>` links β using `routerLink` (which renders a real anchor tag) rather than JavaScript-only navigation is what makes your route structure discoverable by crawling in the first place.
- 2
Client-Side Routing Still Requires Server-Side Rendering for Each Route to Be Indexed
Even with proper `routerLink` usage, a pure client-side-rendered Angular app still sends crawlers an empty shell for every route β Angular Universal or prerendering is what actually makes each route's content visible in the crawled HTML.
Best Practices
Set the Document Title on Every Successful Navigation
Subscribe to the Router's `NavigationEnd` events and call Angular's `Title` service to set a route-specific `<title>` β without this, every route shares whatever title was set in `index.html`, which is both a poor UX and SEO practice.
Always Provide a Wildcard Route for Unmatched URLs
Without a catch-all `path: '**'` route, navigating to a non-existent URL leaves the router outlet blank with no feedback at all β a dedicated 404 component gives users a clear, actionable dead end instead of a confusing empty page.
Frequent Bugs
A styled `<div>` with a click handler calling `router.navigate()` works visually but fails basic accessibility checks.
Replace it with a real `<a routerLink="...">`, styled to match the same design β this restores keyboard focusability, correct screen reader announcement as a link, and native browser features like right-click 'open in new tab' that a div-based fake link can't replicate.
After navigating to a new route, keyboard focus remains on the link that was clicked, and the page doesn't scroll to the top.
Angular's router doesn't handle either of these automatically. Subscribe to `router.events` for `NavigationEnd`, and explicitly call `.focus()` on the new view's main heading and `window.scrollTo(0, 0)` (or use Angular's built-in `scrollPositionRestoration` option) to replicate expected navigation behavior.
Real-World Examples
Router Setup With Title Updates and Scroll Restoration
An app's root routing configuration updates the document title on every navigation and restores scroll position to the top, replicating expected traditional-navigation behavior in a single-page app.
RouterModule.forRoot(routes, { scrollPositionRestoration: 'top' });
router.events.pipe(filter(e => e instanceof NavigationEnd)).subscribe(() => {
titleService.setTitle(getTitleForRoute());
});