Me gustaría advertir a los usuarios de los cambios no guardados antes de que abandonen una página en particular de mi aplicación angular 2. Normalmente lo usaría window.onbeforeunload, pero eso no funciona para aplicaciones de una sola página.
Descubrí que en angular 1, puedes conectarte al $locationChangeStartevento para lanzar una confirmcaja para el usuario, pero no he visto nada que muestre cómo hacer que esto funcione para angular 2, o si ese evento aún está presente. . También he visto complementos para ag1 que brindan funcionalidad para onbeforeunload, pero nuevamente, no he visto ninguna forma de usarlo para ag2.
Espero que alguien más haya encontrado una solución a este problema; cualquier método funcionará bien para mis propósitos.
angular
angular2-routing
Whelch
fuente
fuente

Respuestas:
El enrutador proporciona una devolución de llamada de ciclo de vida CanDeactivate
para más detalles vea el tutorial de guardias
original (enrutador RC.x)
fuente
canDeactivate, no funcionará.Para cubrir también las protecciones contra las actualizaciones del navegador, el cierre de la ventana, etc. (consulte el comentario de @ChristopheVidal a la respuesta de Günter para obtener detalles sobre el problema), me ha resultado útil agregar el
@HostListenerdecorador a lacanDeactivateimplementación de su clase para escuchar elbeforeunloadwindowevento. Cuando se configura correctamente, esto protegerá contra la navegación externa y dentro de la aplicación al mismo tiempo.Por ejemplo:
Componente:
Guardia:
Rutas:
Módulo:
NOTA : Como señaló @JasperRisseeuw, IE y Edge manejan el
beforeunloadevento de manera diferente a otros navegadores e incluirán la palabrafalseen el cuadro de diálogo de confirmación cuando elbeforeunloadevento se active (por ejemplo, el navegador se actualiza, cierra la ventana, etc.). La navegación dentro de la aplicación Angular no se ve afectada y mostrará correctamente el mensaje de advertencia de confirmación designado. Aquellos que necesitan ser compatibles con IE / Edge y no quierenfalsemostrar / quieren un mensaje más detallado en el cuadro de diálogo de confirmación cuandobeforeunloadse activa el evento, también pueden querer ver la respuesta de @ JasperRisseeuw para una solución alternativa.fuente
@Injectable()a la clase PendingChangesGuard. Además, tuve que agregar PendingChangesGuard a mis proveedores en@NgModuleimport { HostListener } from '@angular/core';beforeunload. Si devuelve un Observable, no funcionará. Es posible que desee cambiar su interfaz para algo asícanDeactivate: (internalNavigation: true | undefined)y llame a su componente de esta manera:return component.canDeactivate(true). De esta manera, puede verificar si no está navegando internamente para regresar enfalselugar de un Observable.El ejemplo con @Hostlistener de stewdebaker funciona muy bien, pero hice un cambio más porque IE y Edge muestran el "falso" que devuelve el método canDeactivate () en la clase MyComponent al usuario final.
Componente:
fuente
falseque se muestre en el cuadro de diálogo de confirmación. Hice una pequeña edición a su respuesta para incluirla'$event'en la@HostListeneranotación, ya que es necesaria para poder acceder a ella en launloadNotificationfunción.Implementé la solución de @stewdebaker que funciona muy bien, sin embargo, quería una buena ventana emergente de arranque en lugar de la torpe confirmación estándar de JavaScript. Suponiendo que ya está usando ngx-bootstrap, puede usar la solución de @ stwedebaker, pero cambie el 'Guard' por el que estoy mostrando aquí. También debe presentar
ngx-bootstrap/modaly agregar un nuevoConfirmationComponent:Guardia
(reemplace 'confirmar' con una función que abrirá un modal de arranque, mostrando un nuevo personalizado
ConfirmationComponent):confirmación.componente.html
confirmación.componente.ts
Y dado que el nuevo
ConfirmationComponentse mostrará sin usarselectoren una plantilla html, debe declararseentryComponentsen su raízapp.module.ts(o como sea que nombre su módulo raíz). Realice los siguientes cambios enapp.module.ts:app.module.ts
fuente
La solución fue más fácil de lo esperado, no la use
hrefporque esto no es manejado por larouterLinkdirectiva de uso de Angular Routing .fuente
Respuesta de junio de 2020:
Tenga en cuenta que todas las soluciones propuestas hasta este punto no tratan con un defecto conocido significativo con los
canDeactivateguardias de Angular :Esto se ha discutido aquí , aquí y en detalle aquí.
Consulte mi solución al problema que se muestra aquí, que soluciona de forma segura este problema *. Esto se ha probado en Chrome, Firefox y Edge.
* AVISO IMPORTANTE : En esta etapa, lo anterior borrará el historial de avance cuando se haga clic en el botón Atrás, pero conservará el historial de retroceso. Esta solución no será apropiada si preservar su historial de reenvíos es vital. En mi caso, normalmente uso una estrategia de enrutamiento de detalles maestros cuando se trata de formularios, por lo que mantener el historial de reenvío no es importante.
fuente