Gostaria de avisar os usuários sobre alterações não salvas antes de saírem de uma página específica do meu aplicativo angular 2. Normalmente eu usaria window.onbeforeunload
, mas isso não funciona para aplicativos de página única.
Descobri que no angular 1, você pode conectar o $locationChangeStart
evento para lançar uma confirm
caixa para o usuário, mas não vi nada que mostre como fazer isso funcionar para o angular 2, ou se esse evento ainda está presente . Também vi plug-ins para ag1 que fornecem funcionalidade para onbeforeunload
, mas, novamente, não vi nenhuma maneira de usá-lo para ag2.
Espero que outra pessoa tenha encontrado uma solução para este problema; qualquer um dos métodos funcionará bem para meus propósitos.
angular
angular2-routing
Whelch
fonte
fonte
Respostas:
O roteador fornece um retorno de chamada do ciclo de vida CanDeactivate
para mais detalhes veja o tutorial dos guardas
original (roteador RC.x)
fonte
canDeactivate
, não funcionará.Para cobrir também as proteções contra atualizações do navegador, fechamento de janela, etc. (consulte o comentário de @ChristopheVidal à resposta de Günter para obter detalhes sobre o problema), achei útil adicionar o
@HostListener
decorador àcanDeactivate
implementação de sua classe para ouvir obeforeunload
window
evento. Quando configurado corretamente, isso protegerá contra navegação interna e externa ao mesmo tempo.Por exemplo:
Componente:
Guarda:
Rotas:
Módulo:
NOTA : Como @JasperRisseeuw apontou, o IE e o Edge tratam o
beforeunload
evento de maneira diferente de outros navegadores e incluirão a palavrafalse
na caixa de diálogo de confirmação quando obeforeunload
evento for ativado (por exemplo, o navegador é atualizado, fechando a janela, etc.). A navegação no aplicativo Angular não é afetada e mostrará corretamente a mensagem de aviso de confirmação designada. Aqueles que precisam suportar o IE / Edge e não queremfalse
mostrar / querem uma mensagem mais detalhada na caixa de diálogo de confirmação quando obeforeunload
evento é ativado também podem querer ver a resposta de @JasperRisseeuw para uma solução alternativa.fonte
@Injectable()
à classe PendingChangesGuard. Além disso, tive que adicionar PendingChangesGuard aos meus provedores em@NgModule
import { HostListener } from '@angular/core';
beforeunload
. Se você retornar um Observable, não funcionará. Você pode querer mudar a sua interface para algo comocanDeactivate: (internalNavigation: true | undefined)
e chamar seu componente como este:return component.canDeactivate(true)
. Dessa forma, você pode verificar se não está navegando internamente para retornar aofalse
invés de um Observável.O exemplo com o @Hostlistener de stewdebaker funciona muito bem, mas fiz mais uma alteração porque o IE e o Edge exibem o "false" que é retornado pelo método canDeactivate () na classe MyComponent para o usuário final.
Componente:
fonte
false
que apareça na caixa de diálogo de confirmação. Fiz uma pequena edição em sua resposta para incluir o'$event'
na@HostListener
anotação, pois isso é necessário para poder acessá-lo naunloadNotification
função.Eu implementei a solução de @stewdebaker que funciona muito bem, no entanto, eu queria um pop-up de bootstrap legal em vez da confirmação desajeitada do JavaScript padrão. Supondo que você já esteja usando o ngx-bootstrap, você pode usar a solução de @stwedebaker, mas troque o 'Guarda' pelo que estou mostrando aqui. Você também precisa apresentar
ngx-bootstrap/modal
e adicionar um novoConfirmationComponent
:Guarda
(substitua 'confirmar' por uma função que abrirá um modal de bootstrap - exibindo um novo e personalizado
ConfirmationComponent
):confirmação.componente.html
confirm.component.ts
E uma vez que o novo
ConfirmationComponent
será exibido sem usar umselector
em um modelo html, ele precisa ser declaradoentryComponents
em sua raizapp.module.ts
(ou qualquer que seja o nome do seu módulo raiz). Faça as seguintes alterações emapp.module.ts
:app.module.ts
fonte
A solução foi mais fácil do que o esperado, não use
href
porque isso não é tratado pelarouterLink
diretiva de uso de Roteamento Angular .fonte
Resposta de junho de 2020:
Observe que todas as soluções propostas até este ponto não lidam com uma falha significativa conhecida com os
canDeactivate
guardas da Angular :Isso foi discutido aqui , aqui e longamente aqui
Consulte minha solução para o problema demonstrado aqui, que contorna esse problema com segurança *. Isso foi testado no Chrome, Firefox e Edge.
* AVISO IMPORTANTE : Neste estágio, o procedimento acima limpará o histórico de encaminhamento quando o botão Voltar for clicado, mas preservará o histórico de retorno. Esta solução não será apropriada se preservar seu histórico de encaminhamento for vital. No meu caso, normalmente uso uma estratégia de roteamento de detalhes mestres quando se trata de formulários, portanto, manter o histórico de encaminhamento não é importante.
fonte