I had a similar usecase and solved this using a CanDeactivate - Guard. The upside of this over an CanAvtivate-Guard is that you only need to set the Guard for those components that actually open a Dialog. In my application those were only 2 components.
First i set closeOnNavigation to false, so that the dialog is not closed immediately when the navigation is started:
const matDialogRef = this.matDialog.open(AddAbilityToHeroDialogComponent,
{ ...
closeOnNavigation: false,
});
Second i implemented the Guard - basically i injected MatDialog and check if there are dialogs open. If so i abort the navigation and just close all dialogs.
@Injectable({
providedIn: 'root'
})
export class CloseModalOnBrowserBackIfNecessaryDeactivateGuard implements CanDeactivate<Component> {
constructor(private dialog: MatDialog) {
}
canDeactivate(component: Component, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if (this.dialog.openDialogs.length > 0) {
this.dialog.closeAll();
return false;
} else {
return true;
}
}
}
Finally I added the Guard to the routes that are opening Dialogs like so:
{path: "edit/:id", component: HeroesEditComponent, canDeactivate: [CloseModalOnBrowserBackIfNecessaryDeactivateGuard]}