Navigation isn't just about links. It's about controlling the user's flow based on logic, data, and interactions.
2Visual Feedback: Active Links
A good UI always tells the user where they are. The routerLinkActive directive monitors the current URL and applies a specific CSS class to the element when the route matches. You can also use the [routerLinkActiveOptions] property to specify if the match should be exact (important for the root / path) or partial. This automated behavior saves you from manually managing 'active' states in your component logic.
3Step-by-Step Breakdown
We already know [routerLink] for HTML. But what if we need to navigate after a logic check, like a login?
For programmatic navigation, we inject the 'Router' service into our component's constructor.
Now we can use the 'navigate' method. It takes an array of URL segments. This is identical to clicking a routerLink.
Checkpoint: In TypeScript logic, which service and method do we use to trigger navigation?
- βwindow.location.href = '/path'
- βthis.router.navigate(['/path'])
Back in the template, we often want to highlight the 'active' link. Angular provides 'routerLinkActive' for this.
When the current URL matches the link's path, Angular automatically adds the CSS class you specified. It's magic!
Checkpoint: Which directive is used to apply a CSS class when a route is currently active?
- βrouterLinkActive
- βngClass
Great job! You now have full control over how your users move through your application.
Next, we'll learn how to pass parameters like IDs through the URL.
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)
1A `CanActivate` Guard Redirect Should Explain Why, Not Just Silently Bounce the User
If a guard blocks navigation (e.g., not logged in) and redirects to a login page, pass context (via query params or a shared service) so the destination page can announce *why* the user landed there β a silent redirect with no explanation is disorienting for any user, especially one relying on a screen reader to understand what just happened.
2Programmatic Navigation Triggered by a Non-Link Element Still Needs Full Keyboard Support
If `router.navigate()` is called from a custom control (like a card that navigates on click) rather than a real `routerLink` anchor, that control needs the same `tabindex`, `role`, and keyboard handling any other custom interactive element would require.
SEO Implications
- 1
Guard-Based Redirects Executed Client-Side Are Invisible to Crawlers That Don't Run JavaScript
A `CanActivate` guard that redirects unauthenticated users client-side doesn't produce an HTTP redirect a non-JS crawler would follow β if the guarded content should never be indexed, enforce that at the server/CDN level too, not only in Angular's router.
- 2
Use Real Redirects (Angular's `redirectTo` in Route Config) for Permanent URL Changes
For a route that's permanently moved, configuring `redirectTo` in the route definition is more predictable for both users and crawlers following old links than a one-off `router.navigate()` call buried in component logic.
Best Practices
Prefer Guards Over In-Component Checks for Access Control Logic
A `CanActivate`/`CanActivateChild` guard stops a route from resolving before the component ever instantiates, which is both more secure (no component logic executes at all) and avoids a brief flash of protected content that an in-component redirect-after-render check would cause.
Use Query Parameters for Optional, Bookmarkable State β Not Required Route Data
Query params (`?sort=price&page=2`) are ideal for filter/sort/pagination state that should be shareable via URL, but shouldn't be relied upon for anything the route genuinely requires to function β use path parameters or route resolvers for that instead.
Frequent Bugs
A protected page briefly flashes its content before redirecting an unauthenticated user to login.
Access control was implemented as a check inside the component (e.g., in `ngOnInit`) rather than as a `CanActivate` route guard β a guard runs before the route resolves and the component is created at all, preventing that flash of protected content entirely.
Query parameters used for a filter/sort UI disappear unexpectedly after some other navigation elsewhere in the app.
A later `router.navigate()` call (perhaps triggered by an unrelated action) didn't preserve the existing query params, silently clearing them. Use `queryParamsHandling: 'preserve'` (or `'merge'`) in that navigation call if the existing query state should carry forward.
Real-World Examples
Auth Guard Preventing Protected Route Access
A route guard checks authentication status before a protected route resolves, redirecting to login with context about the original destination rather than letting protected content flash briefly or silently bouncing the user with no explanation.
canActivate(route: ActivatedRouteSnapshot): boolean {
if (this.auth.isLoggedIn()) return true;
this.router.navigate(['/login'], { queryParams: { returnUrl: route.url.join('/') } });
return false;
}