Programmatic Navigation and Route Guards
Not all navigation happens via [routerLink] in templates. Sometimes you need to navigate in response to code — after a form submission, after a timeout, or when a condition is met. Angular’s Router service provides programmatic navigation. Route guards let you intercept navigation to protect routes.
Programmatic navigation with Router
Section titled “Programmatic navigation with Router”Inject the Router service and call navigate():
import { Component } from '@angular/core';import { Router } from '@angular/router';import { FormsModule } from '@angular/forms';
@Component({ standalone: true, imports: [FormsModule], template: ` <input [(ngModel)]="query" (keydown.enter)="search()" placeholder="Search..." /> `})export class NavBar { query = '';
constructor(private router: Router) {}
search(): void { if (this.query.trim()) { this.router.navigate(['/search'], { queryParams: { q: this.query } }); this.query = ''; } }}navigate() accepts the same arguments as [routerLink]: an array of path segments and an optional options object with queryParams, fragment, and other settings.
Route guards with CanActivateFn
Section titled “Route guards with CanActivateFn”A route guard is a function that runs before a route is activated. It returns true to allow navigation, false to block it, or a UrlTree to redirect elsewhere.
In Angular 15+, guards are plain functions (not classes), which makes them simple to write and test:
import { inject } from '@angular/core';import { CanActivateFn, Router } from '@angular/router';import { WatchlistService } from '../services/watchlist.service';import { ToastService } from '../services/toast.service';
export const watchlistGuard: CanActivateFn = () => { const watchlist = inject(WatchlistService); const router = inject(Router); const toast = inject(ToastService);
if (watchlist.count() > 0) { return true; }
toast.show('Add a movie to your watchlist first.'); return router.createUrlTree(['/browse']);};Register the guard on the route:
{ path: 'watchlist', component: Watchlist, canActivate: [watchlistGuard] }When a user navigates to /watchlist:
- The guard runs
- If the watchlist is empty, it shows a toast notification and redirects to
/browse - If the watchlist has items, it returns
trueand theWatchlistcomponent renders
Guards as side-effect machines
Section titled “Guards as side-effect machines”This example demonstrates something important: guards are not limited to binary allow/deny decisions. The watchlistGuard shows a toast message before redirecting. Guards can call services, log analytics, check auth tokens, fetch data — anything that needs to happen before a route activates.
inject() in guards
Section titled “inject() in guards”Notice that the guard uses inject() instead of constructor injection. Since the guard is a function (not a class), there is no constructor. The inject() function is Angular’s alternative — it retrieves a service from the DI system and can be called at the top level of a function that runs inside an injection context (such as guard execution).
Router.createUrlTree()
Section titled “Router.createUrlTree()”router.createUrlTree(['/browse']) creates a UrlTree object representing the /browse URL. Returning a UrlTree from a guard causes Angular to redirect to that URL instead of activating the original route.
Exercise
Section titled “Exercise”- Create a
WatchlistGuardin your practice project that checks ahasItemsflag. - If
hasItemsis false, log a message and redirect to'/'. - If
hasItemsis true, returntrue. - Apply the guard to a
/protectedroute. - Navigate to
/protectedwithhasItems = falseand confirm you are redirected. SethasItems = trueand confirm you can access the route.
Router.navigate(['/path'])navigates programmatically — useful after form submissions, timeouts, or conditional logic.CanActivateFnguards are plain functions that run before a route activates.- Return
trueto allow,falseto block, orrouter.createUrlTree(['/path'])to redirect. - Guards can inject services with
inject()and trigger side effects before making their decision. - Register guards on routes with
canActivate: [myGuard].