Dec 5, 2025

Angular CanDeactivate Guard: Prevent Losing Unsaved Changes Like a Pro

Tags

Let me share a story from when I first built a form-heavy Angular app. I was excited to let users enter data and edit their profiles. But one day, I accidentally navigated away from my half-filled form—and poof—all the unsaved work was gone. Annoying, right? That’s when I discovered Angular’s CanDeactivate guard, which saves us from exactly that because it checks if you can leave a route, perfect for warning users about unsaved changes.


candeactivate-guard


What’s the Problem?


Imagine you’re filling a lengthy profile form or writing a blog post. If you click a link or the browser’s back button accidentally before saving, you lose everything. That’s sad UX and often leads to complaints. CanDeactivate gives you a way to intervene and ask the user, “Hey, you have unsaved changes. Are you sure you want to leave?”


How I Implemented CanDeactivate Guard


Here’s a simple way I created a general-purpose CanDeactivateGuard for different components that might have unsaved changes.


Step 1: Define an Interface for Components That Support Deactivation Check


I made an interface to enforce a canDeactivate method on components where leaving could cause data loss.


// can-deactivate.guard.ts
export interface CanComponentDeactivate {
  canDeactivate: () => boolean | Promise<boolean>;
}


This means any component that wants to use the guard must implement this method.

Step 2: Create the Guard Service


This service checks if the component allows navigation away or not:


import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { CanComponentDeactivate } from './can-deactivate.guard';
import { Observable } from 'rxjs';

type allowVal = boolean | Promise<boolean> | Observable<boolean>

@Injectable({ providedIn: 'root' })
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
  canDeactivate(
    component: CanComponentDeactivate
  ): allowVal {
    return component.canDeactivate ? component.canDeactivate() : true;
  }
}



Step 3: Implement canDeactivate in Your Component


Here’s how I did it in my ProfileEditorComponent:


export class ProfileEditorComponent implements CanComponentDeactivate {
  formDirty = false; // This should be true if user changed form data

  canDeactivate(): boolean {
    if (this.formDirty) {
      return confirm('You have changes that to be saved. Leave anyway?');
    }
    return true;
  }
}


Whenever the user tries to leave the page, this function triggers and prompts them.


Step 4: Register Guard in Routing Module


In your app routing, attach the guard to routes like this:


const routes = [
  { path: 'profile-edit', component: ProfileEditorComponent, canDeactivate: [CanDeactivateGuard] },
  // other routes ...
];


That’s it! Now Angular checks before leaving the route.


Why This Works Really Well for Me


  • Reusable Guard: I can easily apply this same guard to multiple forms by implementing the interface.
  • User Friendly: Users get a warning before losing data accidentally.
  • Sync or Async: Works with both synchronous confirms or async dialogs (like modals).
  • Simple and Clean: Keeps the component focused on UI & form handling.

Something I Learned


I initially forgot to implement the interface in my component, so the guard always returned true and navigation was never blocked. Making sure your components have the canDeactivate() method fixed that.

Also, integrating modal confirmation dialogs instead of confirm() is powerful for better UX, and it smoothly integrates with this guard.


If you’re working on Angular forms or any page where data loss is risky, CanDeactivate is your safety net. Implement it just like I showed, and never again worry about unsaved changes disappearing!


EmoticonEmoticon