I stumbled upon this question quite a bit after the fact, but I hope to help someone else coming here.
The principal candidate for a solution is a route guard.
See here for an explanation:
https://angular.io/guide/router#candeactivate-handling-unsaved-changes
The relevant part (copied almost verbatim) is this implementation:
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { CanDeactivate,
ActivatedRouteSnapshot,
RouterStateSnapshot } from '@angular/router';
import { MyComponent} from './my-component/my-component.component';
@Injectable({ providedIn: 'root' })
export class CanDeactivateGuard implements CanDeactivate<MyComponent> {
canDeactivate(
component: MyComponent,
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | boolean {
// you can just return true or false synchronously
if (expression === true) {
return true;
}
// or, you can also handle the guard asynchronously, e.g.
// asking the user for confirmation.
return component.dialogService.confirm('Discard changes?');
}
}
Where MyComponent is your custom component and CanDeactivateGuard is going to be registered in your AppModule in the providers section and, more importantly, in your routing config in the canDeactivate array property:
{
path: 'somePath',
component: MyComponent,
canDeactivate: [CanDeactivateGuard]
},