CanDeactivate Guard in Angular Tutorial

beginner
10 min

CanDeactivate Guard in Angular Tutorial

Welcome to our comprehensive guide on Angular's CanDeactivate Guard! In this lesson, we'll delve into this powerful feature, explaining its purpose, importance, and practical usage.

What is CanDeactivate Guard? 🎯

The CanDeactivate Guard is a mechanism in Angular that allows you to prevent a component from navigating away until certain conditions are met. This is particularly useful when you have a form with unsaved changes and you want to ensure that the user confirms they want to leave.

Why use CanDeactivate Guard? 💡

Say goodbye to annoying pop-ups asking if you're sure you want to leave a form with unsaved changes! CanDeactivate Guard lets you implement this functionality elegantly and seamlessly, enhancing the user experience of your Angular applications.

Getting Started 📝

To implement a CanDeactivate Guard, follow these steps:

  1. Create a new service.
bash
ng generate service canDeactivate
  1. Implement the canDeactivate method in the service.
typescript
import { Observable, of } from 'rxjs'; import { CanDeactivate } from '@angular/router'; export class CanDeactivateGuard implements CanDeactivate<any> { canDeactivate(component: any): Observable<boolean> | Promise<boolean> | boolean { if (component.form.dirty) { return confirm('You have unsaved changes. Are you sure you want to leave?'); } return true; } }
  1. Register the guard in your route.
typescript
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { FormComponent } from './form.component'; import { CanDeactivateGuard } from './can-deactivate.guard'; const routes: Routes = [ { path: '', component: FormComponent, canDeactivate: [CanDeactivateGuard] }, ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule], }) export class FormRoutingModule {}

Advanced Example ✅

Let's take a look at a more complex example where we have a FormComponent with multiple tabs, and we want to implement CanDeactivate Guard for each tab.

typescript
import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { CanDeactivateGuard } from './can-deactivate.guard'; @Component({ selector: 'app-form', templateUrl: './form.component.html', styleUrls: ['./form.component.css'], }) export class FormComponent { form: FormGroup; constructor(private fb: FormBuilder, private route: ActivatedRoute, private router: Router) { this.form = this.fb.group({ tab1: ['', Validators.required], tab2: ['', Validators.required], }); } navigate(route: string) { this.router.navigate([route]); } }

In this example, we have a FormComponent with two tabs, each having a form with required fields. We'll implement the CanDeactivate Guard for both tabs.

typescript
import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { CanDeactivateGuard } from './can-deactivate.guard'; export class Tab1Component { form: FormGroup; constructor(private fb: FormBuilder, private route: ActivatedRoute, private router: Router) { this.form = this.fb.group({ tab1: ['', Validators.required], }); } navigate() { this.router.navigate(['..'], { relativeTo: this.route }); } } export class Tab2Component { form: FormGroup; constructor(private fb: FormBuilder, private route: ActivatedRoute, private router: Router) { this.form = this.fb.group({ tab2: ['', Validators.required], }); } navigate() { this.router.navigate(['..'], { relativeTo: this.route }); } }

Finally, we update our CanDeactivate Guard to handle the tabs:

typescript
import { Component } from '@angular/core'; import { CanDeactivate } from '@angular/router'; import { Observable, of } from 'rxjs'; export class CanDeactivateGuard implements CanDeactivate<any> { canDeactivate(component: any): Observable<boolean> | Promise<boolean> | boolean { if (component instanceof Tab1Component && component.form.dirty) { return confirm('You have unsaved changes in Tab 1. Are you sure you want to leave?'); } if (component instanceof Tab2Component && component.form.dirty) { return confirm('You have unsaved changes in Tab 2. Are you sure you want to leave?'); } return true; } }

Now, when the user navigates away from the form, Angular will check if any of the tabs have unsaved changes and prompt the user accordingly.

Quiz 📝

Quick Quiz
Question 1 of 1

What does the `CanDeactivate` Guard do in Angular?