Per coprire anche le protezioni contro gli aggiornamenti del browser, la chiusura della finestra, ecc. (Vedere il commento di @ ChristopheVidal alla risposta di Günter per i dettagli sul problema), ho trovato utile aggiungere il @HostListener
decoratore canDeactivate
all'implementazione della tua classe per ascoltare l' beforeunload
window
evento. Se configurato correttamente, proteggerà dalla navigazione sia in-app che esterna allo stesso tempo.
Per esempio:
Componente:
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
}
}
Guardia:
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.');
}
}
Itinerari:
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] },
];
Modulo:
import { PendingChangesGuard } from './pending-changes.guard';
import { NgModule } from '@angular/core';
@NgModule({
// ...
providers: [PendingChangesGuard],
// ...
})
export class AppModule {}
NOTA : come ha sottolineato @JasperRisseeuw, IE ed Edge gestiscono l' beforeunload
evento in modo diverso dagli altri browser e includeranno la parola false
nella finestra di dialogo di conferma quando l' beforeunload
evento si attiva (ad esempio, il browser si aggiorna, chiude la finestra, ecc.). La navigazione all'interno dell'app Angular non viene modificata e mostrerà correttamente il messaggio di avviso di conferma designato. Coloro che hanno bisogno di supportare IE / Edge e non vogliono false
mostrare / volere un messaggio più dettagliato nella finestra di dialogo di conferma quando l' beforeunload
evento si attiva potrebbero anche voler vedere la risposta di @ JasperRisseeuw per una soluzione alternativa.