← Back to Articles         
What is CanDeactivate in Angular?

What is CanDeactivate in Angular?

Published on 30 Sep 2026     7 min read Angular
Route Guards

What is CanDeactivate in Angular?

What is CanDeactivate?

CanDeactivate is an Angular route guard used to determine whether a user is allowed to leave the current route/component.

It is commonly used when a user has unsaved changes in a form.

For example:

User editing Product
        ↓
Changes are not saved
        ↓
User clicks Home
        ↓
CanDeactivate Guard
        ↓
"Are you sure you want to leave?"
       / \
     Yes  No
      ↓    ↓
   Leave  Stay

In modern Angular, we commonly use:

CanDeactivateFn

Why Do We Need CanDeactivate?

Suppose a user is editing:

/products/edit/10

They change:

Product Name
Price
Description

but forget to click Save.

Then they click:

Home

Without CanDeactivate:

Edit Product
     ↓
Click Home
     ↓
Home Page
     ↓
Changes Lost

With CanDeactivate:

Edit Product
     ↓
Click Home
     ↓
CanDeactivate
     ↓
Unsaved changes?
     ↓
Yes
     ↓
"Are you sure?"

This helps prevent accidental data loss.


Full Simple Sample Program

We'll create an Edit Product page.

If the user changes the product name without saving, Angular asks for confirmation before leaving.

edit-product.ts

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-edit-product',
  standalone: true,
  imports: [FormsModule],
  template: `
    <h2>Edit Product</h2>

    <label>Product Name:</label>

    <input
      type="text"
      [(ngModel)]="productName"
      (ngModelChange)="onChange()">

    <br><br>

    <button (click)="save()">
      Save
    </button>
  `
})
export class EditProduct {

  productName = 'Laptop';

  hasUnsavedChanges = false;

  onChange(): void {
    this.hasUnsavedChanges = true;
  }

  save(): void {
    console.log('Product saved');

    this.hasUnsavedChanges = false;
  }

  canLeave(): boolean {

    if (!this.hasUnsavedChanges) {
      return true;
    }

    return confirm(
      'You have unsaved changes. Do you want to leave?'
    );
  }
}

unsaved-changes.guard.ts

import { CanDeactivateFn } from '@angular/router';

import { EditProduct } from './edit-product';

export const unsavedChangesGuard:
  CanDeactivateFn<EditProduct> =
  (component) => {

    return component.canLeave();
  };

home.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-home',
  standalone: true,
  template: `
    <h2>Home Page</h2>
  `
})
export class Home {
}

app.routes.ts

import { Routes } from '@angular/router';

import { Home } from './home';
import { EditProduct } from './edit-product';

import { unsavedChangesGuard }
  from './unsaved-changes.guard';

export const routes: Routes = [
  {
    path: '',
    component: Home
  },
  {
    path: 'products/edit/:id',
    component: EditProduct,

    canDeactivate: [
      unsavedChangesGuard
    ]
  }
];

app.ts

import { Component } from '@angular/core';
import {
  RouterLink,
  RouterOutlet
} from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    RouterLink,
    RouterOutlet
  ],
  template: `
    <h1>My Application</h1>

    <nav>
      <a routerLink="/">Home</a> |
      <a routerLink="/products/edit/10">
        Edit Product
      </a>
    </nav>

    <hr>

    <router-outlet></router-outlet>
  `
})
export class App {
}

app.config.ts

import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes)
  ]
};

How Does It Work?

The important route configuration is:

{
  path: 'products/edit/:id',
  component: EditProduct,

  canDeactivate: [
    unsavedChangesGuard
  ]
}

This tells Angular:

Before leaving EditProduct, execute unsavedChangesGuard.


Step 1: User Opens Edit Page

/products/edit/10

The component initially has:

hasUnsavedChanges = false;

Step 2: User Changes the Product

When the user changes the input:

(ngModelChange)="onChange()"

Angular executes:

onChange(): void {
  this.hasUnsavedChanges = true;
}

Now:

hasUnsavedChanges = true

Step 3: User Tries to Leave

Suppose the user clicks:

Home

Angular does not immediately leave.

It first executes:

unsavedChangesGuard

The guard calls:

component.canLeave();

Step 4: Check Unsaved Changes

The component contains:

canLeave(): boolean {

  if (!this.hasUnsavedChanges) {
    return true;
  }

  return confirm(
    'You have unsaved changes. Do you want to leave?'
  );
}

If there are no changes:

return true;

Angular allows navigation.

If there are unsaved changes:

confirm(...)

is displayed.


Complete Flow

User opens Edit Product
        ↓
Changes product name
        ↓
hasUnsavedChanges = true
        ↓
Clicks Home
        ↓
CanDeactivate guard executes
        ↓
component.canLeave()
        ↓
Unsaved changes?
     /          \
   No            Yes
   ↓              ↓
 true          confirm()
   ↓           /      \
Leave        OK       Cancel
              ↓          ↓
            true        false
              ↓          ↓
            Leave       Stay

CanActivate vs CanDeactivate

This is an important interview distinction.

CanActivate CanDeactivate
Controls entering a route Controls leaving a route
Runs before route activation Runs before leaving current route
Common for authentication Common for unsaved changes
CanActivateFn CanDeactivateFn<T>
“Can I enter?” “Can I leave?”

Think:

CanActivate
     ↓
Can I ENTER?


CanDeactivate
     ↓
Can I LEAVE?

Understanding CanDeactivateFn<EditProduct>

Look at:

CanDeactivateFn<EditProduct>

The generic type:

<EditProduct>

tells Angular that this guard is associated with an EditProduct component.

Therefore, the guard receives the component instance:

(component) => {

and can access its properties and methods:

component.hasUnsavedChanges

component.canLeave()

This is one major difference from CanActivate.

CanDeactivate can inspect the component being left.


A Better Reusable Approach

In a larger application, you may have several forms:

Edit Product
Edit Customer
Edit Order
Edit Profile

Instead of making a guard depend specifically on EditProduct, define a common interface.

Interface

export interface CanComponentDeactivate {

  canDeactivate(): boolean;
}

Component

export class EditProduct
  implements CanComponentDeactivate {

  hasUnsavedChanges = false;

  canDeactivate(): boolean {

    if (!this.hasUnsavedChanges) {
      return true;
    }

    return confirm(
      'You have unsaved changes. Do you want to leave?'
    );
  }
}

Guard

import { CanDeactivateFn } from '@angular/router';

import { CanComponentDeactivate }
  from './can-component-deactivate';

export const unsavedChangesGuard:
  CanDeactivateFn<CanComponentDeactivate> =
  (component) => {

    return component.canDeactivate();
  };

Now the same guard can be reused for:

EditProduct
EditCustomer
EditOrder
EditProfile

This is a cleaner design for larger applications.


What Can CanDeactivate Return?

Like other Angular guards, it can return navigation decisions synchronously or asynchronously.

Allow

return true;

Means:

Allow the user to leave.

Block

return false;

Means:

Stay on the current page.

Redirect

A guard can also return a redirect result when appropriate.

It can additionally use:

Promise
Observable

for asynchronous checks.


Older Angular: Class-Based CanDeactivate

Older Angular applications commonly used a class-based guard.

import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';

import { EditProduct } from './edit-product';

@Injectable({
  providedIn: 'root'
})
export class UnsavedChangesGuard
  implements CanDeactivate<EditProduct> {

  canDeactivate(
    component: EditProduct
  ): boolean {

    return component.canLeave();
  }
}

Route:

{
  path: 'products/edit/:id',
  component: EditProduct,

  canDeactivate: [
    UnsavedChangesGuard
  ]
}

Modern Angular commonly uses the functional version:

export const unsavedChangesGuard:
  CanDeactivateFn<EditProduct> =
  (component) => {

    return component.canLeave();
  };

So:

Older Angular
      ↓
Class implements CanDeactivate


Modern Angular
      ↓
CanDeactivateFn<T>
      ↓
Functional Guard

Advantages

  • Prevents accidental loss of unsaved data.
  • Useful for forms and edit screens.
  • Allows confirmation before leaving.
  • Can inspect the current component.
  • Can be reused across multiple forms.
  • Supports synchronous and asynchronous checks.

Disadvantages / Considerations

  • It only controls navigation performed through Angular Router.
  • Browser refresh, tab closing, or closing the browser is a different browser lifecycle concern and may require additional handling.
  • Too many confirmation dialogs can create poor UX.
  • The application must correctly determine whether the form is actually dirty/unsaved.

For Angular forms, you can often use form state such as:

form.dirty

instead of manually maintaining:

hasUnsavedChanges

Key Points

  • CanDeactivate controls whether a user can leave a route.
  • Modern Angular uses:
CanDeactivateFn<T>
  • Configure it using:
canDeactivate: [unsavedChangesGuard]
  • Common use case:
Unsaved form changes
  • true → allow leaving.
  • false → stay on the current route.
  • The guard receives the current component instance.
  • It can work with Promise and Observable.
  • A reusable interface is useful when multiple components need the same unsaved-changes behavior.

Interview Questions and Answers

1. What is CanDeactivate?

CanDeactivate is an Angular route guard that determines whether a user can leave the currently activated route.


2. What is the most common use of CanDeactivate?

The most common use is preventing users from accidentally leaving a form with unsaved changes.


3. How do you configure CanDeactivate?

{
  path: 'products/edit/:id',
  component: EditProduct,
  canDeactivate: [unsavedChangesGuard]
}

4. What happens when it returns true?

return true;

Angular allows the user to leave the current route.


5. What happens when it returns false?

return false;

Angular cancels the navigation, so the user remains on the current route.


6. What is the difference between CanActivate and CanDeactivate?

CanActivate
    ↓
Can the user ENTER the route?


CanDeactivate
    ↓
Can the user LEAVE the route?

CanActivate is commonly used for authentication/authorization, while CanDeactivate is commonly used for unsaved changes.


7. Why does CanDeactivateFn have a generic type?

For example:

CanDeactivateFn<EditProduct>

The generic type identifies the component being deactivated, allowing the guard to access that component instance:

component.canLeave()

8. Can CanDeactivate be asynchronous?

Yes. It can return asynchronous guard results using a Promise or Observable.


Interview-ready answer

CanDeactivate is an Angular route guard used to determine whether a user can leave the current route. It is commonly used to prevent users from accidentally leaving a form with unsaved changes. In modern Angular, it is implemented using CanDeactivateFn<T>. Returning true allows navigation, while returning false cancels navigation and keeps the user on the current page.

← Back to Articles