Lab 08: Deactivate Guard
π Resourcesβ
π Starter Codeβ
step-8-album-wholesale-v16-auth-guard
In this lab, you'll prevent users from accidentally losing unsaved form data by implementing a CanDeactivate guard. You'll create a functional guard that prompts users for confirmation, implement the deactivation logic in your component, and optionally replace browser confirm dialogs with Material Dialog.
π Instructionsβ
Step 1: Create Deactivate Guardβ
Create a functional guard:
import { CanDeactivateFn } from '@angular/router';
export interface CanComponentDeactivate {
canDeactivate: () => boolean;
}
export const canDeactivateGuard: CanDeactivateFn<CanComponentDeactivate> = (component) => {
if (component.canDeactivate && !component.canDeactivate()) {
return confirm('You have unsaved changes. Leave anyway?');
}
return true;
};
Step 2: Implement in Componentβ
Add canDeactivate method to component:
export class AlbumAddComponent implements CanComponentDeactivate {
private formSubmitted = false;
canDeactivate(): boolean {
return !this.albumForm.dirty || this.formSubmitted;
}
saveAlbum() {
this.formSubmitted = true;
// Save logic...
}
}
Step 3: Apply to Routeβ
Add guard to route:
const routes: Routes = [
{
path: 'albums/add',
component: AlbumAddComponent,
canDeactivate: [canDeactivateGuard]
}
];
Bonus Step: Use MatDialog Instead of confirm()β
Replace browser confirm() with Material Dialog:
import { inject } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ConfirmDialogComponent } from './confirm-dialog.component';
export const canDeactivateGuard: CanDeactivateFn<CanComponentDeactivate> = (component) => {
if (component.canDeactivate && !component.canDeactivate()) {
const dialog = inject(MatDialog);
return dialog.open(ConfirmDialogComponent, {
data: { message: 'You have unsaved changes. Leave anyway?' }
}).afterClosed();
}
return true;
};
Simple confirmation dialog component:
@Component({
selector: 'app-confirm-dialog',
template: `
<h2 mat-dialog-title>Confirm</h2>
<mat-dialog-content>{{ data.message }}</mat-dialog-content>
<mat-dialog-actions>
<button mat-button [mat-dialog-close]="false">Cancel</button>
<button mat-button [mat-dialog-close]="true" color="warn">Leave</button>
</mat-dialog-actions>
`
})
export class ConfirmDialogComponent {
data = inject(MAT_DIALOG_DATA);
}