Displaying PrimeNG confirmation dialog with guarded routes

Oleg Varaksin
3 min readMar 5, 2017

--

In Angular 2+, you can protect routes with guards. The most likely used guard types are CanActivate and CanDeactivate. The first guard type decides if a route can be activated, and the second one decides if a route can be deactivated. In this blog post, we will discuss CanDeactivate. This is an interface having only one method canDeactivate.

This method can return Observable<boolean>, Promise<boolean> or boolean. If the value of boolean is true, the user can navigate away from the route. If the value of boolean is false, the user will stay on the same view. If you want to protect your route from navigating away under some circumstances, you have to do three steps:

  • Create a class that implements the interface CanDeactivate . The class acts as a guard which will be checked by the router when navigating away from the current view. As you can see, the interface expects a generic component class. This is the current component rendered within the <router-outlet> tag.
  • Register this guard as provider in a module annotated with @NgModule.
  • Add this guard to the route configuration. A route configuration has the property canDeactivate where such guards can be added multiple times.

You might want to check out an example from the official Angular documentation. In this blog post, we would like to implement a typical use case where we will check if there are some unsaved input changes made by user. If the current view has unsaved input values and the user tries to navigate away to another view, a confirmation dialog should be shown. We will use ConfirmDialog from the PrimeNG UI library for Angular 2+.

Now, hitting the Yes button leads to navigating to another view.

Hitting the No button, prevent the the process of navigating from the current route. Let’s create the first view with an input element, a submit button and PrimeNG component <p-confirmDialog>.

The corresponding component for this template keeps the dirty state of the form which indicates that the form is being edited.

We will not implement any sophisticated algorithms in order to check if the input value was really changed. We just check the form’s dirty state. If the form is not being edited, the navigation on submit should be fine. No need to ask the user about unsaved changes. Now, we have to inject the PrimeNG ConfirmationService into our guard implementation, which is required to display a confirmation dialog, and use it like this within the canDeactivate method:

But there is a problem. The confirm method doesn’t return required Observable<boolean>, Promise<boolean> or boolean. The solution is to create and return an Observable object by invoking Observable.create(). The create method expects a callback with one parameter: observer: Observer<boolean>. Now we need to do two steps:

  • Put the call this.confirmationService.confirm() into the callback’s body.
  • Pass true or false to the subscriber by invoking observer.next(true) and observer.next(false) respectively. The subscriber is the PrimeNG’s component ConfirmDialog which needs to be informed about user’s choice.

The full implementation of the UnsavedChangesGuard is shown below.

If you prefer Promise instead of Observable, you can return Promise as follows:

The complete project is available on GitHub: https://github.com/ova2/frontend-tooling-tutorial/tree/master/angular-playground/router-primeng-confirmdialog

--

--

Oleg Varaksin
Oleg Varaksin

Written by Oleg Varaksin

Thoughts on software development. Author of “PrimeFaces Cookbook” and “Angular UI Development with PrimeNG”. My old blog: http://ovaraksin.blogspot.de

Responses (2)