Implementing a CanDeactivate Guard in Angular
Angular's CanDeactivate guard allows you to prevent navigation away from a component. This is crucial for scenarios where a user might be in the middle of filling out a form or performing an action that shouldn't be interrupted without saving or confirmation. This challenge asks you to implement a CanDeactivate guard that prompts the user to confirm navigation if they have unsaved changes in a component.
Problem Description
You need to create a CanDeactivate guard in Angular that checks for unsaved changes in a component before allowing navigation away from it. The guard should:
- Check for Unsaved Changes: The guard will receive a component as an argument. This component will have a method called
hasUnsavedChanges()which returns a boolean indicating whether there are unsaved changes. - Prompt the User: If
hasUnsavedChanges()returnstrue, the guard should display a confirmation dialog to the user asking if they want to leave the page. The dialog should include a "Stay" and a "Leave" button. - Handle User Response:
- If the user clicks "Stay," navigation should be prevented, and the guard should return
false. - If the user clicks "Leave," navigation should be allowed, and the guard should return
true.
- If the user clicks "Stay," navigation should be prevented, and the guard should return
- Allow Navigation Without Confirmation: If
hasUnsavedChanges()returnsfalse, the guard should allow navigation without prompting the user and returntrue.
Expected Behavior:
- When a user attempts to navigate away from a component with unsaved changes, a confirmation dialog appears.
- If the user confirms they want to leave, navigation proceeds.
- If the user chooses to stay, navigation is blocked.
- If the component has no unsaved changes, navigation proceeds without interruption.
Edge Cases to Consider:
- What happens if the component doesn't implement the
hasUnsavedChanges()method? (Assume it should default to allowing navigation -true). - How should the dialog be displayed? (For simplicity, assume a basic
alertis sufficient for this challenge, though a more sophisticated modal would be preferred in a real-world application). - What if the user cancels the navigation in some other way (e.g., closing the browser tab)? This is not a primary concern for this challenge.
Examples
Example 1:
Input: Component with hasUnsavedChanges() returning true. User attempts to navigate away.
Output: Confirmation dialog appears with "Stay" and "Leave" buttons. User clicks "Leave".
Explanation: Navigation proceeds.
Example 2:
Input: Component with hasUnsavedChanges() returning true. User attempts to navigate away.
Output: Confirmation dialog appears with "Stay" and "Leave" buttons. User clicks "Stay".
Explanation: Navigation is blocked.
Example 3:
Input: Component with hasUnsavedChanges() returning false. User attempts to navigate away.
Output: Navigation proceeds without any prompt.
Explanation: No confirmation dialog is displayed.
Constraints
- The guard must be injectable and reusable across different components.
- The
hasUnsavedChanges()method is assumed to be present on the component being guarded. If not, default to allowing navigation. - Use a simple
alertdialog for demonstration purposes. Do not implement a full-fledged modal. - The solution must be written in TypeScript and compatible with a standard Angular project setup.
Notes
- Consider using Angular's dependency injection to provide the component to the guard.
- The
ActivatedRouteSnapshotandCanDeactivateFn<T>types are important for understanding the guard's context. - Think about how to handle the asynchronous nature of dialogs (although a simple
alertis synchronous). - Focus on the core logic of checking for unsaved changes and prompting the user. Styling and advanced dialog implementations are outside the scope of this challenge.