Advanced Routing & State Handling: Lazy Loading with Feature Modules; Route Guards (CanActivate, CanDeactivate); Route Resolvers; advanced state handling using RxJS Subjects and Behavior Subjects

Beyond basic navigation, Angular gives you lazy loading to load pages only when needed, route guards to allow or block navigation, resolvers to fetch data before a page shows, and RxJS Subjects to share changing state across components.

12 min read · 8 cards · 2 checks

Read in: English · हिन्दी · ગુજરાતી


Theory

Smarter navigation and shared state

Basic routing maps a URL to a component. Real apps need more: load heavy pages only when visited, stop unauthorised users reaching a page, warn before leaving a half-filled form, and have data ready the moment a page appears. And components across the app often need to share the same changing state, like who is logged in.

Angular provides four tools for this: lazy loading, route guards, resolvers, and RxJS Subjects. This lesson introduces each, so FestConnect can navigate intelligently and keep its state in sync.

At a glance

ToolWhat it does
Lazy loadingLoads a route's code only when the user navigates there (smaller initial load)
CanActivate guardDecides whether a route may be ENTERED (e.g. must be logged in)
CanDeactivate guardDecides whether the user may LEAVE (e.g. warn about unsaved changes)
ResolverFetches data BEFORE the route activates, so the page has it ready
RxJS Subject / BehaviorSubjectShares changing state across components (BehaviorSubject also holds a current value)

Practical

Lazy loading and a functional route guard

import { Routes } from '@angular/router';
import { inject } from '@angular/core';
import { AuthService } from './auth.service';

// A functional CanActivate guard (Angular 17 style)
const authGuard = () => inject(AuthService).isLoggedIn();

export const routes: Routes = [
  { path: 'events', loadComponent: () =>            // lazy: loaded on demand
      import('./events/events.component').then(m => m.EventsComponent) },
  { path: 'profile', canActivate: [authGuard],      // blocked unless logged in
      loadComponent: () =>
      import('./profile/profile.component').then(m => m.ProfileComponent) },
];

Theory

Guards, resolvers, and why they help

CanActivate runs before a route loads and returns true or false: FestConnect can block /profile unless the user is logged in. CanDeactivate runs when the user tries to leave: if they have unsaved changes in the registration form, it can warn them first. Resolvers fetch a route's data in advance, so the events page opens with its list already loaded, no flash of empty screen.

Together they make navigation feel deliberate and safe: the right people reach the right pages, at the right time, with data ready.

Practical

BehaviorSubject for shared state (the current user)

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class AuthService {
  // BehaviorSubject holds a CURRENT value and emits it to new subscribers
  private userSubject = new BehaviorSubject<string | null>(null);
  user$ = this.userSubject.asObservable();

  login(name: string) { this.userSubject.next(name); }   // push a new value
  logout()            { this.userSubject.next(null); }
}
// Any component can subscribe to user$ and always get the latest logged-in user.

Quiz

You want to prevent users from opening the /profile page unless they are logged in. Which routing tool fits?

  1. A resolver, because it fetches data
  2. A CanActivate guard, which decides whether a route may be entered
  3. Lazy loading, because it hides the page
  4. A CanDeactivate guard, because it controls leaving
Show the answer

A CanActivate guard, which decides whether a route may be entered

A CanActivate guard runs before a route is entered and returns true or false, so it is exactly what blocks /profile unless the user is logged in. Option A, a resolver, pre-fetches DATA for a route; it does not decide whether entry is allowed. Option C, lazy loading, controls WHEN a route's code is loaded (on demand) for performance; it does not enforce access rules. Option D, CanDeactivate, controls LEAVING a route (like warning about unsaved changes), which is the opposite direction from what we need here. Entering a route is guarded by CanActivate; leaving it by CanDeactivate.

Think first

Why does a BehaviorSubject suit shared app state better than a plain Subject?

Both a Subject and a BehaviorSubject broadcast values. Why prefer BehaviorSubject for state like the current user? Then tap.

Show the answer

Because a BehaviorSubject remembers its CURRENT value and immediately gives it to any component that subscribes later, whereas a plain Subject only emits to those already listening at the moment a value is pushed. Consider the logged-in user in FestConnect. Suppose the user logs in early, and then a component elsewhere (a navbar, a profile widget) subscribes AFTERWARD to find out who is logged in. With a plain Subject, that late subscriber would hear nothing until the NEXT time a value happens to be pushed, so it would not know the user until they log in or out again, leaving the UI out of sync. A BehaviorSubject, by contrast, is created with (or holds) a current value and replays that latest value to every new subscriber the instant they subscribe, so the navbar immediately learns the user is already logged in. That 'always has a current value to hand out' behaviour is exactly what shared STATE needs: state is a thing that has a value at all times, and any component asking should get the present value, not just future changes. A plain Subject is better for one-off EVENTS (a button click, a notification) where there is no meaningful 'current value' to replay. So the rule of thumb is: BehaviorSubject for state (current value matters), Subject for events (only the moment matters). Current-value replay is what makes BehaviorSubject the right tool for app state.

Summary

Key takeaways

  • Lazy loading loads a route's code only when the user navigates there, shrinking the initial bundle.
  • CanActivate guards decide whether a route may be entered (e.g. must be logged in); Angular 17 uses functional guards.
  • CanDeactivate guards decide whether the user may leave (e.g. warn about unsaved changes).
  • Resolvers fetch a route's data before it activates, so the page opens with data ready.
  • RxJS Subjects share changing state across components; a BehaviorSubject also holds a current value.
  • BehaviorSubject suits app state (like the current user) because it replays the latest value to new subscribers.
  • Memory hook: lazy-load for speed, guards for access, resolvers for data, BehaviorSubject for shared state.

Study this properly

This page is the lesson to read. In Gri-Learn the same topic is a graded deck: the self-checks are scored and your weak topics are tracked. Free to start.

Start this topic

Already have an account? Sign in

More from Fundamentals of Angular (v17) for Single Page Applications

Gri-Learn · syllabus-mapped B.C.A. lessons in English, Hindi and Gujarati

Advanced Routing & State Handling: Lazy Loading with Feature Modules; Route Guards (CanActivate, CanDeactivate); Route Resolvers; advanced state handling using RxJS Subjects and Behavior Subjects · Fundamentals of Full Stack Web Development (Major-15-01) · Gri-Learn