Hone logo
Hone
Problems

Implement a CanDeactivate Guard for Unsaved Changes in Angular

This challenge focuses on creating a CanDeactivate guard in Angular. This guard is crucial for preventing users from accidentally losing unsaved data when navigating away from a form or a page that requires user input. You will implement logic to check for unsaved changes and prompt the user before allowing navigation.

Problem Description

Your task is to create a CanDeactivate guard that protects a specific route from being left if the user has unsaved changes. This is a common requirement in web applications, especially for forms where users might be entering data.

Key Requirements:

  1. Create a CanDeactivate Guard: Implement a class that implements the CanDeactivate interface from @angular/router.
  2. Detect Unsaved Changes: Within the guard, you need a mechanism to determine if there are unsaved changes. For this challenge, we will simulate this by using a simple boolean flag within the component being protected.
  3. Prompt the User: If unsaved changes are detected, the guard should present a confirmation dialog (using window.confirm for simplicity) to the user, asking if they really want to leave.
  4. Control Navigation:
    • If the user confirms they want to leave, allow navigation.
    • If the user cancels, prevent navigation.
  5. Apply the Guard: Configure your Angular application's routing module to apply this guard to a designated route.
  6. Component Integration: Create a simple component that the guard will protect. This component should have a mechanism to set and unset the "unsaved changes" flag.

Expected Behavior:

  • When a user navigates to the protected route and there are no unsaved changes, navigation should proceed normally.
  • When a user navigates to the protected route and there are unsaved changes, a confirmation dialog should appear.
    • If the user clicks "OK" (or equivalent), navigation proceeds.
    • If the user clicks "Cancel" (or equivalent), navigation is blocked, and the user remains on the current page.
  • When a user navigates away from the protected route, and there are unsaved changes, the same confirmation dialog should appear.

Edge Cases to Consider:

  • What happens if the component being protected hasn't been initialized yet? (The guard should handle this gracefully.)
  • How does the guard behave when navigating to a child route within the protected route? (For this challenge, focus on leaving the entire protected route.)

Examples

This challenge doesn't have traditional input/output like a function. Instead, we'll describe the user experience.

Scenario 1: No Unsaved Changes

  • User Action: Navigates to the protected "Edit Profile" page. No changes have been made to the form. Then, clicks a link to navigate to the "Dashboard" page.
  • Expected Behavior: The user is immediately navigated to the "Dashboard" page. No confirmation dialog is shown.

Scenario 2: With Unsaved Changes - User Confirms Leaving

  • User Action: Navigates to the protected "Edit Profile" page. Types some text into a profile description field (triggering the "unsaved changes" flag). Then, clicks a link to navigate to the "Dashboard" page.
  • Expected Behavior:
    1. A confirmation dialog appears with a message like "You have unsaved changes. Are you sure you want to leave?"
    2. The user clicks "OK".
    3. The user is navigated to the "Dashboard" page.

Scenario 3: With Unsaved Changes - User Cancels Leaving

  • User Action: Navigates to the protected "Edit Profile" page. Types some text into a profile description field (triggering the "unsaved changes" flag). Then, clicks a link to navigate to the "Dashboard" page.
  • Expected Behavior:
    1. A confirmation dialog appears with a message like "You have unsaved changes. Are you sure you want to leave?"
    2. The user clicks "Cancel".
    3. The user remains on the "Edit Profile" page, and the "Dashboard" page is not loaded.

Constraints

  • The solution must be implemented in TypeScript using Angular.
  • Use the @angular/router module for routing.
  • For simplicity, simulate the detection of unsaved changes using a boolean property within the component. No actual form dirty checking logic is required.
  • Use window.confirm() for displaying the confirmation prompt.
  • The guard should be applied to a single, designated route.

Notes

  • CanDeactivate Interface: The CanDeactivate interface has a canDeactivate method that takes the component instance, currentRoute, currentState, nextState, and historyState as arguments.
  • Component Type: You will need to specify the type of the component being deactivated in the generic type parameter of CanDeactivate<T>.
  • Simulating Changes: In your protected component, you'll need a public property (e.g., hasUnsavedChanges: boolean = false) and methods to set/unset it (e.g., markAsDirty(), markAsPristine()).
  • Routing Configuration: Remember to provide the guard in your module and add it to the canDeactivate property in your route configuration.
  • Return Type: The canDeactivate method must return a boolean, an Observable<boolean>, a Promise<boolean>, or UrlTree. For this challenge, a boolean or Observable<boolean> is sufficient.

Good luck! This is a fundamental concept in building robust Angular applications.

Loading editor...
typescript