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 $locationChangeStart
evento para lanzar una confirm
caja 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
@HostListener
decorador a lacanDeactivate
implementación de su clase para escuchar elbeforeunload
window
evento. 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
beforeunload
evento de manera diferente a otros navegadores e incluirán la palabrafalse
en el cuadro de diálogo de confirmación cuando elbeforeunload
evento 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 quierenfalse
mostrar / quieren un mensaje más detallado en el cuadro de diálogo de confirmación cuandobeforeunload
se 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@NgModule
import { 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 enfalse
lugar 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
false
que 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@HostListener
anotación, ya que es necesaria para poder acceder a ella en launloadNotification
funció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/modal
y 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
ConfirmationComponent
se mostrará sin usarselector
en una plantilla html, debe declararseentryComponents
en 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
href
porque esto no es manejado por larouterLink
directiva 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
canDeactivate
guardias 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