Angular 15: Transitioning deprecated CanDeactivate() to Functional Guards
jun

jun @junlow

About: A design-minded front-end developer focused on building beautiful interfaces & experiences. Loves being multidisciplinary, problem-solving, and learning new things.

Joined:
Oct 9, 2019

Angular 15: Transitioning deprecated CanDeactivate() to Functional Guards

Publish Date: Sep 7 '23
24 8

As developers, we often find ourselves adapting to changes in the tools and frameworks we use. Recently, while working on my Angular project, I stumbled upon a significant shift in Angular 15: the deprecation of class-based route guards like CanDeactivate(). In their place, Angular has introduced functional guards, providing a more modern and flexible approach to managing route deactivation. In this article, I'll guide you through this transition and share how you can smoothly update your codebase. ✨

Understanding the Change

In previous Angular versions, we used the CanDeactivate() guard to handle route deactivation, implementing custom logic to determine whether a user could leave a particular route. However, Angular 15 introduces functional guards as the new way forward. This change aligns with Angular's mission to simplify and enhance the development experience.

Transitioning to Functional Guards

1) Create a Functional Guard: Start by creating a TypeScript function as your functional guard. This function should return true to allow deactivation or false to prevent it.

export const hasUnsavedChangesGuard: CanDeactivateFn<ComponentCanDeactivate> = (component: ComponentCanDeactivate): Observable<boolean> => {
   if (component.canDeactivate && component.canDeactivate()) {
      return true;
    }
   if (!component.confirm()) {
      return confirm('Are you sure you want to leave this page? If you do, any unsaved changes will be lost.');
    }
}
Enter fullscreen mode Exit fullscreen mode

2) Implement the Functional Guard: In your routing configuration, specify the functional guard for a route.

const routes: Routes = [
  {
    path: 'my-component',
    component: MyComponent,
    canDeactivate: [hasUnsavedChangesGuard],
  },
];
Enter fullscreen mode Exit fullscreen mode

Alternatively, you can use an injectable class as a functional guard by leveraging the inject function. This approach keeps your guard logic separate from your routing configuration, especially for the case you have your custom component such as Dialog component.

const routes: Routes = [
  {
    path: 'my-component',
    component: MyComponent,
    canDeactivate: [() => inject(hasUnsavedChangesGuard).canDeactivate()]
  },
];
Enter fullscreen mode Exit fullscreen mode

Conclusion

By embracing this change in Angular 15, you'll find your route guard implementation becomes more streamlined and adaptable. For detailed examples and additional information, refer to the official Angular documentation.

Change in the development world is inevitable, and adapting to it is key to staying at the forefront of technology. As I worked through this transition in Angular 15, I found it not only improved the development experience but also reinforced the idea that growth and improvement are constants in the world of software development. Embrace these changes, and you'll continue to build better, more maintainable applications 😄🚀

Comments 8 total

  • Rahul Dubey
    Rahul DubeySep 8, 2023

    getting no output whenever ng serve cmd run on terminal.

    • jun
      junSep 10, 2023

      Hi Rahul, there could be various factors on whether deactivation is permitted. I've updated the post with guard and component logic examples. Also, You may check if you've correctly passed your guard in the module's providers (app.module.ts).

      Here is the guide with application example from angular docs. I hope it helps.

      • Rahul Dubey
        Rahul DubeySep 10, 2023

        Image description

        here is screenshot!
        this cmd didn't through any error dunring ng server runs command. and not starting this project.

        • jun
          junSep 12, 2023

          It seems you're using a different Angular version and don't seem to be related to this article. Check out the link in my last reply about the application guide a look or just go ahead npm install again.

  • Vijay.H.Yadav
    Vijay.H.YadavNov 29, 2023

    Hello,
    Could please share unit test for above code ?
    Thanks in advance.

    • jun
      junNov 29, 2023

      You can simply create a mock component has a canDeactivate method and ensure it works correctly :)

  • Peter Boos
    Peter BoosJul 10, 2024

    So i'm upgrading from 15 to 18.. and its still deprecated ?
    Why is the Angular community (google) so in love with deprecating instead of having things done multiple ways, each time a new design ideas comes out, they push anyone to follow it.
    This isn't nice if you do large projects, and have to keep up with their avantgarde design goals.

    If they deprecate and it is really needed (which i doubt a bit in this case), then say after date X we stop this functionality.. though that would alert people and they don't want to upset the public and run their language as if it was a fashion show.

    • jun
      junJul 12, 2024

      Hey Peter, when I wrote the post, it was happened when I upgrade to v15 last year. After v15, you should refer to the latest official documentation: angular.dev/api/router/CanDeactivate.

Add comment