Voici mon problème, j'ai deux vues (View1 et View2) et un contrôleur pour chaque vue (Ctrl1 et Ctrl2). Dans View1, j'essaie d'avertir l'utilisateur avant qu'il ne quitte la page accidentellement sans enregistrer les modifications.
J'utilise window.onbeforeunload, ce qui fonctionne très bien, mais mon problème est que même si je n'ai onbeforeunload que sur un contrôleur, l'événement semble également être déclenché dans le deuxième contrôleur! Mais je n'ai même pas eu cet événement là-dedans. Lorsque l'utilisateur quitte une page et qu'il y a des modifications non enregistrées, il est averti par onbeforeunload, si l'utilisateur rejette l'alerte et quitte la page, est-il ramené à la deuxième vue, si l'utilisateur essaie de quitter maintenant cette autre vue, nous serions également prévenus des modifications non enregistrées! Quand ce n'est même pas le cas! Pourquoi cela arrive-t-il?
J'utilise également $ locationChangeStart, qui fonctionne très bien, mais uniquement lorsque l'utilisateur modifie l'itinéraire, pas lorsqu'il actualise le navigateur, appuie sur 'retour' ou essaie de le fermer, c'est pourquoi je suis obligé d'utiliser onbeforeunload ( Si vous avez une meilleure approche, veuillez me le faire savoir). Toute aide ou meilleure approche serait grandement appréciée!
//In this controller I check for window.onbeforeunload
app.controller("Ctrl1", function ($scope, ...)){
window.onbeforeunload = function (event) {
//Check if there was any change, if no changes, then simply let the user leave
if(!$scope.form.$dirty){
return;
}
var message = 'If you leave this page you are going to lose all unsaved changes, are you sure you want to leave?';
if (typeof event == 'undefined') {
event = window.event;
}
if (event) {
event.returnValue = message;
}
return message;
}
//This works only when user changes routes, not when user refreshes the browsers, goes to previous page or try to close the browser
$scope.$on('$locationChangeStart', function( event ) {
if (!$scope.form.$dirty) return;
var answer = confirm('If you leave this page you are going to lose all unsaved changes, are you sure you want to leave?')
if (!answer) {
event.preventDefault();
}
});
}
//This other controller has no window.onbeforeunload, yet the event is triggered here too!
app.controller("Ctrl2", function ($scope, ...)){
//Other cool stuff ...
}
J'ai essayé de vérifier le chemin actuel avec $ location.path () pour avertir uniquement l'utilisateur lorsqu'il est dans la vue que je veux que l'onbeforeunload soit déclenché, mais cela semble un peu `` hacky '' la solution serait de ne pas exécuter onbeforeunload sur l'autre contrôleur du tout.
J'ai ajouté $ location.path ()! = '/ View1' dans le premier qui semble fonctionner, mais cela ne me semble pas juste, d'ailleurs je n'ai pas seulement deux vues, je avoir plusieurs vues et cela deviendrait difficile avec plus de contrôleurs impliqués:
app.controller("Ctrl1", function ($scope, ...)){
window.onbeforeunload = function (event) {
//Check if there was any change, if no changes, then simply let the user leave
if($location.path() != '/view1' || !$scope.form.$dirty){
return;
}
var message = 'If you leave this page you are going to lose all unsaved changes, are you sure you want to leave?';
if (typeof event == 'undefined') {
event = window.event;
}
if (event) {
event.returnValue = message;
}
return message;
}
//This works only when user changes routes, not when user refreshes the browsers, goes to previous page or try to close the browser
$scope.$on('$locationChangeStart', function( event ) {
if (!$scope.form.$dirty) return;
var answer = confirm('If you leave this page you are going to lose all unsaved changes, are you sure you want to leave?')
if (!answer) {
event.preventDefault();
}
});
}
Désenregistrez l'événement onbeforeunload lorsque le contrôleur qui l'a défini sort du domaine:
$scope.$on('$destroy', function() {
delete window.onbeforeunload;
});
J'ai juste essayé la solution ci-dessus, et cela ne fonctionnait pas pour moi. Même en tapant manuellement delete window.onbeforeunload
dans la console ne supprimerait pas la fonction. J'avais plutôt besoin de définir la propriété sur undefined.
$scope.$on('$destroy', function(e){
$window.onbeforeunload = undefined;
});
Pour ceux d'entre vous qui utilisent angular-ui-router vous utiliseriez est $stateChangeStart
au lieu de $locationChangeStart
, par exemple.
$scope.$on('$stateChangeStart', function (event){
if (forbit){
event.preventDefault()
}
else{
return
}
})
En guise de mise à jour, pour toute personne utilisant un routeur ui angulaire, je passerais maintenant $ transitions dans votre contrôleur et l'utiliser;
$transitions.onStart({}, function ($transition)
{
$transition.abort();
//return false;
});