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.
What’s the Problem?
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
// 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
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!
