Pour couvrir également les protections contre les actualisations du navigateur, la fermeture de la fenêtre, etc. (voir le commentaire de @ ChristopheVidal à la réponse de Günter pour plus de détails sur le problème), j'ai trouvé utile d'ajouter le @HostListener
décorateur à l' canDeactivate
implémentation de votre classe pour écouter l' beforeunload
window
événement. Une fois configuré correctement, cela protégera à la fois la navigation dans l'application et la navigation externe.
Par exemple:
Composant:
import { ComponentCanDeactivate } from './pending-changes.guard';
import { HostListener } from '@angular/core';
import { Observable } from 'rxjs/Observable';
export class MyComponent implements ComponentCanDeactivate {
// @HostListener allows us to also guard against browser refresh, close, etc.
@HostListener('window:beforeunload')
canDeactivate(): Observable<boolean> | boolean {
// insert logic to check if there are pending changes here;
// returning true will navigate without confirmation
// returning false will show a confirm dialog before navigating away
}
}
Garde:
import { CanDeactivate } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
export interface ComponentCanDeactivate {
canDeactivate: () => boolean | Observable<boolean>;
}
@Injectable()
export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
// if there are no pending changes, just allow deactivation; else confirm first
return component.canDeactivate() ?
true :
// NOTE: this warning message will only be shown when navigating elsewhere within your angular app;
// when navigating away from your angular app, the browser will show a generic warning message
// see http://stackoverflow.com/a/42207299/7307355
confirm('WARNING: You have unsaved changes. Press Cancel to go back and save these changes, or OK to lose these changes.');
}
}
Itinéraires:
import { PendingChangesGuard } from './pending-changes.guard';
import { MyComponent } from './my.component';
import { Routes } from '@angular/router';
export const MY_ROUTES: Routes = [
{ path: '', component: MyComponent, canDeactivate: [PendingChangesGuard] },
];
Module:
import { PendingChangesGuard } from './pending-changes.guard';
import { NgModule } from '@angular/core';
@NgModule({
// ...
providers: [PendingChangesGuard],
// ...
})
export class AppModule {}
REMARQUE : Comme @JasperRisseeuw l'a souligné, IE et Edge gèrent l' beforeunload
événement différemment des autres navigateurs et incluront le mot false
dans la boîte de dialogue de confirmation lorsque l' beforeunload
événement s'activera (par exemple, le navigateur s'actualise, ferme la fenêtre, etc.). La navigation dans l'application Angular n'est pas affectée et affichera correctement votre message d'avertissement de confirmation désigné. Ceux qui ont besoin de prendre en charge IE / Edge et qui ne veulent false
pas afficher / veulent un message plus détaillé dans la boîte de dialogue de confirmation lorsque l' beforeunload
événement s'active peuvent également vouloir voir la réponse de @ JasperRisseeuw pour une solution de contournement.