loading...

Prevent navigation when a modal/dialog is open in Angular 9

antal_meckl profile image Meckl Antal ・1 min read

tl;dr: Use guards to close any open dialog, and to prevent unwanted navigation.

I was struggling with this issue on many of my previous projects, especially when the requirement was to create a PWA/mobile app, where modals usually are rendered full-screen.

I was using similar solutions, like one explained in this post.

The basic idea is that when we open a modal, we are actually not navigating between routes, but from a UX perspective, users expect that the modal will close when they hit the back button, which is not happening.

This is extremely infuriating when we have a full-screen modal, because repeatedly hitting the back button will not close the modal, but instead just navigate back and back on the website without the user noticing.

The solution I recently came up with uses guards. For this example I'm using Ionic 5.

@Injectable({
  providedIn: 'root',
})
export class ModalGuard implements CanActivate {
  constructor(private readonly modalController: ModalController) {}

  canActivate(
    _next: ActivatedRouteSnapshot,
    _state: RouterStateSnapshot
  ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    return this.modalController.getTop().then((modal) => {
      if (modal) {
        this.modalController.dismiss();
        return false;
      }
      return true;
    });
  }
}

And I use this guard for my every route.

const routes: Routes = [
  {
    path: '',
    canActivate: [ModalGuard],
    component: TestPage,
  },
];

This guard will prevent the navigation if a modal is open, and it will close it.

Discussion

markdown guide