typescript 32 lines · 5 steps

How a functional route guard works in Angular

A CanActivateFn checks authentication and either allows navigation or redirects to the login page.

Explained by highlit
1import { inject } from '@angular/core';
2import {
3 ActivatedRouteSnapshot,
4 CanActivateFn,
5 Router,
6 RouterStateSnapshot,
7 UrlTree,
8} from '@angular/router';
9import { map, take } from 'rxjs/operators';
10import { Observable } from 'rxjs';
11import { AuthService } from './auth.service';
12 
13export const authGuard: CanActivateFn = (
14 route: ActivatedRouteSnapshot,
15 state: RouterStateSnapshot,
16): Observable<boolean | UrlTree> => {
17 const auth = inject(AuthService);
18 const router = inject(Router);
19 
20 return auth.isAuthenticated$.pipe(
21 take(1),
22 map((isAuthenticated) => {
23 if (isAuthenticated) {
24 return true;
25 }
26 
27 return router.createUrlTree(['/login'], {
28 queryParams: { returnUrl: state.url },
29 });
30 }),
31 );
32};
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Functional guards use inject() to grab services instead of a constructor, keeping them lightweight and tree-shakable.
  2. 2take(1) completes the stream after one emission so the guard resolves promptly instead of leaving navigation hanging.
  3. 3Returning a UrlTree from a guard is Angular's idiom for redirecting rather than manually calling navigate.

Related explainers

typescript
import { registerLocaleData } from '@angular/common';
import localeFr from '@angular/common/locales/fr';
import localeFrExtra from '@angular/common/locales/extra/fr';
import localeDe from '@angular/common/locales/de';

Locale-aware bootstrapping in Angular

i18n localization dependency-injection
Intermediate 8 steps
typescript
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import * as Joi from 'joi';
 

Validating env config at boot in NestJS

configuration schema-validation environment-variables
Intermediate 8 steps
java
@Component
@Converter
public class EncryptedStringConverter implements AttributeConverter<String, String> {
 

Transparent column encryption in Spring & JPA

encryption aes-gcm jpa-converter
Advanced 10 steps
python
import time
import uuid
 
from django.utils.deprecation import MiddlewareMixin

Attaching per-request context in Django

middleware request lifecycle multi-tenancy
Intermediate 7 steps
typescript
import { Inject, Injectable, Logger } from '@nestjs/common';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';
import { InjectRepository } from '@nestjs/typeorm';

A cache-aside country lookup in NestJS

cache-aside dependency-injection batch-lookup
Intermediate 8 steps
java
package com.acme.billing.config;
 
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;

Feature-flagged beans with Spring @ConditionalOnProperty

feature-flags conditional-beans strategy-pattern
Intermediate 5 steps

Share this explainer

Here's the card — post it anywhere.

How a functional route guard works in Angular — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code