myHotTake

Tag: CanDeactivate tips

  • CanActivate vs CanDeactivate: What’s the Difference?

    If you find this analogy helpful, feel free to like or share it! Let’s jump in.


    I think of CanActivate and CanDeactivate like two types of bouncers at an exclusive treehouse. I’m the treehouse owner, and I have two special bouncers working for me: one stands at the bottom of the ladder (CanActivate) and one hangs out inside the treehouse by the exit door (CanDeactivate).

    The CanActivate bouncer’s job is to decide, “Are you allowed to climb up the ladder and join the fun in the treehouse?” They check things like, “Do you have the secret password? Are you wearing the official badge?” If you meet the criteria, up you go. If not, they politely send you away.

    Now, once someone’s in the treehouse, things change. Enter the CanDeactivate bouncer. This bouncer’s job is to ensure people leave the treehouse in a responsible way. Imagine someone is about to climb down the ladder, but they forgot to take their valuables with them. The CanDeactivate bouncer might say, “Hold up! You’re not leaving until you grab your stuff.” Or, if it’s unsafe to climb down because it’s raining, they might stop someone from leaving altogether.

    The magic of these bouncers? They ensure the treehouse stays organized and safe—one controls who enters, and the other manages how and when people leave. Together, they make sure the treehouse experience is smooth for everyone.


    In Angular, CanActivate and CanDeactivate are route guards. Think of them as the bouncers we talked about: deciding who gets to enter a route and who is allowed to leave a route, respectively.

    CanActivate (The Bottom-Ladder Bouncer)

    Here’s an example of a CanActivate guard that ensures only logged-in users can access a particular route:

    import { Injectable } from '@angular/core';
    import { CanActivate } from '@angular/router';
    import { AuthService } from './auth.service';
    
    @Injectable({
      providedIn: 'root',
    })
    export class AuthGuard implements CanActivate {
      constructor(private authService: AuthService) {}
    
      canActivate(): boolean {
        if (this.authService.isLoggedIn()) {
          console.log('Access granted by CanActivate.');
          return true; // Let them climb the ladder
        } else {
          console.log('Access denied by CanActivate.');
          return false; // Deny access
        }
      }
    }
    

    This is our CanActivate guard checking, “Do you have the secret password (logged in)? If yes, go ahead. If no, sorry, try again later.”

    CanDeactivate (The Exit Door Bouncer)

    Now, here’s an example of a CanDeactivate guard ensuring users don’t accidentally leave a form page with unsaved changes:

    import { Injectable } from '@angular/core';
    import { CanDeactivate } from '@angular/router';
    import { FormComponent } from './form.component';
    
    @Injectable({
      providedIn: 'root',
    })
    export class UnsavedChangesGuard implements CanDeactivate<FormComponent> {
      canDeactivate(component: FormComponent): boolean {
        if (component.hasUnsavedChanges()) {
          return confirm('You have unsaved changes. Do you really want to leave?');
        }
        return true; // Allow exit
      }
    }
    

    Here, the guard asks, “Wait, have you grabbed all your valuables (saved changes)? If not, you’ll need to confirm before climbing down.”

    Applying the Guards in a Route

    You can add these guards to your routes in the app-routing.module.ts file like this:

    import { AuthGuard } from './auth.guard';
    import { UnsavedChangesGuard } from './unsaved-changes.guard';
    
    const routes = [
      {
        path: 'treehouse',
        component: TreehouseComponent,
        canActivate: [AuthGuard], // Guard the ladder
      },
      {
        path: 'form',
        component: FormComponent,
        canDeactivate: [UnsavedChangesGuard], // Guard the exit
      },
    ];
    

    Key Takeaways / Final Thoughts

    • CanActivate guards are like the bouncer at the entrance: they control access to a route by deciding if someone can “enter the treehouse.”
    • CanDeactivate guards are like the bouncer at the exit: they ensure people don’t leave the treehouse in a mess (e.g., leaving unsaved work behind).
    • Using these guards together ensures your app remains secure and user-friendly, guiding users through the right flow.