Tutorial Series Part 1: Building a Multi-Page Angular App with Route Guards

Date: May 4, 2023


Introduction

Building a scalable Angular application often means splitting your app into multiple pages or feature modules, protecting certain routes based on user authentication, and optimizing performance with lazy loading.

In this tutorial, we’ll create a multi-page Angular app featuring:

  • Router configuration
  • Lazy loading of feature modules
  • Route guards to protect authenticated and unauthenticated routes

By the end, you’ll understand how to structure your app for maintainability and security.


Step 1: Setup Angular Project and Routing

Create a new Angular project with routing enabled:

ng new multi-page-app --routing
cd multi-page-app

The CLI generates an app-routing.module.ts for central routing setup.


Step 2: Create Feature Modules for Pages

Let’s create two feature modules — Home and Dashboard.

ng generate module features/home --route home --module app.module
ng generate module features/dashboard --route dashboard --module app.module

This command sets up lazy-loaded routes for /home and /dashboard.


Step 3: Understanding Lazy Loading

Lazy loading means Angular will only load the code for a module when the user navigates to that route, improving initial load time.

Generated app-routing.module.ts looks like:

const routes: Routes = [
  {
    path: 'home',
    loadChildren: () => import('./features/home/home.module').then(m => m.HomeModule)
  },
  {
    path: 'dashboard',
    loadChildren: () => import('./features/dashboard/dashboard.module').then(m => m.DashboardModule)
  },
  { path: '', redirectTo: 'home', pathMatch: 'full' },
];

Step 4: Create Route Guards

Route guards help control access to routes.

Generate an AuthGuard to protect routes that require authentication:

ng generate guard guards/auth

Implement the guard in auth.guard.ts:

import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private router: Router) {}

  isAuthenticated(): boolean {
    // Replace with real auth check logic
    return !!localStorage.getItem('userToken');
  }

  canActivate(): boolean {
    if (this.isAuthenticated()) {
      return true;
    }
    this.router.navigate(['/home']);
    return false;
  }
}

Step 5: Protect Routes Using the Guard

Update dashboard route to use the guard:

{
  path: 'dashboard',
  loadChildren: () => import('./features/dashboard/dashboard.module').then(m => m.DashboardModule),
  canActivate: [AuthGuard]
}

Now, users can access /dashboard only if authenticated.


Step 6: Create an Unauthenticated Guard (Optional)

Similarly, create a guard to prevent logged-in users from visiting public pages like login:

ng generate guard guards/no-auth
canActivate(): boolean {
  if (!this.isAuthenticated()) {
    return true;
  }
  this.router.navigate(['/dashboard']);
  return false;
}

Use on /home or login route as needed.


Step 7: Navigating Between Pages

Use Angular’s routerLink for navigation:

<nav>
  <a routerLink="/home">Home</a>
  <a routerLink="/dashboard">Dashboard</a>
</nav>
<router-outlet></router-outlet>

Bonus: Route Guard Testing

You can write simple unit tests for guards using Jasmine:

describe('AuthGuard', () => {
  let guard: AuthGuard;
  let routerSpy = jasmine.createSpyObj('Router', ['navigate']);

  beforeEach(() => {
    guard = new AuthGuard(routerSpy);
  });

  it('should allow activation when authenticated', () => {
    localStorage.setItem('userToken', 'token');
    expect(guard.canActivate()).toBeTrue();
  });

  it('should redirect to home when not authenticated', () => {
    localStorage.removeItem('userToken');
    expect(guard.canActivate()).toBeFalse();
    expect(routerSpy.navigate).toHaveBeenCalledWith(['/home']);
  });
});

Summary

In this tutorial, we covered:

  • Setting up lazy-loaded routes with Angular Router
  • Creating and applying route guards for authentication
  • Basic navigation and guard testing

This setup lays the foundation for scalable and secure Angular apps.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *