Je souhaite avertir les utilisateurs des modifications non enregistrées avant de quitter une page particulière de mon application angular 2. Normalement, j'utiliserais window.onbeforeunload
, mais cela ne fonctionne pas pour les applications d'une seule page.
J'ai trouvé que dans angular 1, vous pouvez vous connecter à l' $locationChangeStart
événement pour lancer une confirm
boîte pour l'utilisateur, mais je n'ai rien vu qui montre comment faire fonctionner cela pour angular 2, ou si cet événement est même toujours présent . J'ai également vu des plugins pour ag1 qui fournissent des fonctionnalités pour onbeforeunload
, mais encore une fois, je n'ai vu aucun moyen de l'utiliser pour ag2.
J'espère que quelqu'un d'autre a trouvé une solution à ce problème; l'une ou l'autre méthode fonctionnera bien pour mes besoins.
la source
Réponses:
Le routeur fournit un rappel de cycle de vie CanDeactivate
pour plus de détails, voir le tutoriel sur les gardes
d'origine (routeur RC.x)
la source
canDeactivate
cela ne fonctionnera pas.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:
Garde:
Itinéraires:
Module:
REMARQUE : Comme @JasperRisseeuw l'a souligné, IE et Edge gèrent l'
beforeunload
événement différemment des autres navigateurs et incluront le motfalse
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 veulentfalse
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.la source
@Injectable()
à la classe PendingChangesGuard. De plus, j'ai dû ajouter PendingChangesGuard à mes fournisseurs en@NgModule
import { HostListener } from '@angular/core';
beforeunload
. Si vous renvoyez un observable, cela ne fonctionnera pas. Vous pouvez modifier votre interface pour quelque chose commecanDeactivate: (internalNavigation: true | undefined)
et appeler votre composant comme ceci:return component.canDeactivate(true)
. De cette façon, vous pouvez vérifier si vous ne naviguez pas en interne pour revenirfalse
au lieu d'un observable.L'exemple avec @Hostlistener de stewdebaker fonctionne très bien, mais j'y ai apporté une autre modification car IE et Edge affichent le "false" qui est retourné par la méthode canDeactivate () sur la classe MyComponent à l'utilisateur final.
Composant:
la source
false
s'affiche dans la boîte de dialogue de confirmation. J'ai apporté une petite modification à votre réponse pour inclure le'$event'
dans l'@HostListener
annotation, car cela est nécessaire pour pouvoir y accéder dans launloadNotification
fonction.J'ai implémenté la solution de @stewdebaker qui fonctionne très bien, mais je voulais une belle fenêtre contextuelle de démarrage au lieu du JavaScript standard maladroit. En supposant que vous utilisez déjà ngx-bootstrap, vous pouvez utiliser la solution de @ stwedebaker, mais remplacez le «Guard» par celui que je montre ici. Vous devez également introduire
ngx-bootstrap/modal
et ajouter un nouveauConfirmationComponent
:Garde
(remplacez 'confirm' par une fonction qui ouvrira un modal bootstrap - affichant un nouveau, personnalisé
ConfirmationComponent
):confirmation.component.html
confirmation.component.ts
Et puisque le nouveau
ConfirmationComponent
sera affiché sans utiliser deselector
dans un modèle html, il doit être déclaréentryComponents
dans votre racineapp.module.ts
(ou quel que soit votre nom de module racine). Apportez les modifications suivantes àapp.module.ts
:app.module.ts
la source
La solution était plus facile que prévu, ne l'utilisez pas
href
car elle n'est pas gérée par larouterLink
directive d' utilisation du routage angulaire à la place.la source
Réponse de juin 2020:
Notez que toutes les solutions proposées jusqu'à présent ne traitent pas d'un défaut connu significatif des
canDeactivate
gardes Angular :Cela a été discuté ici , ici et en détail ici
Veuillez consulter ma solution au problème illustré ici qui fonctionne en toute sécurité autour de ce problème *. Cela a été testé sur Chrome, Firefox et Edge.
* AVERTISSEMENT IMPORTANT : À ce stade, ce qui précède effacera l'historique de transfert lorsque le bouton de retour est cliqué, mais conservera l'historique de retour. Cette solution ne sera pas appropriée si la préservation de votre historique avant est vitale. Dans mon cas, j'utilise généralement une stratégie de routage maître-détails en ce qui concerne les formulaires, il n'est donc pas important de conserver l'historique avant.
la source