web-dev-qa-db-fra.com

window.onbeforeunload - Afficher uniquement un avertissement lorsque vous ne soumettez pas de formulaire

J'utilise window.onbeforeunload pour empêcher l'utilisateur de s'éloigner après avoir modifié les valeurs d'un formulaire. Cela fonctionne bien, sauf qu'il affiche également l'avertissement lorsque l'utilisateur soumet le formulaire (non souhaité).

Comment puis-je le faire sans afficher l'avertissement lorsque le formulaire est envoyé?

Code actuel:

var formHasChanged = false;

$(document).on('change', 'form.confirm-navigation-form input, form.confirm-navigation-form select, form.confirm-navigation-form textarea', function (e) {
    formHasChanged = true;
});

$(document).ready(function () {
    window.onbeforeunload = function (e) {
        if (formHasChanged) {
            var message = "You have not saved your changes.", e = e || window.event;
            if (e) {
                e.returnValue = message;
            }
            return message;
        }
    }
});
31
mtmurdock

L'utilisation de l'événement d'envoi du formulaire pour définir un indicateur peut vous convenir.

 var formHasChanged = false;
 var submitted = false;

$(document).on('change', 'form.confirm-navigation-form input, form.confirm-navigation-form select, form.confirm-navigation-form textarea', function (e) {
    formHasChanged = true;
});

$(document).ready(function () {
    window.onbeforeunload = function (e) {
        if (formHasChanged && !submitted) {
            var message = "You have not saved your changes.", e = e || window.event;
            if (e) {
                e.returnValue = message;
            }
            return message;
        }
    }
 $("form").submit(function() {
     submitted = true;
     });
});
34
Jay Tomten

vous pouvez utiliser .on () pour lier onbeforeunload puis utiliser .off () pour le dissocier dans la soumission du formulaire

$(document).ready(function () {
    // Warning
    $(window).on('beforeunload', function(){
        return "Any changes will be lost";
    });

    // Form Submit
    $(document).on("submit", "form", function(event){
        // disable warning
        $(window).off('beforeunload');
    });
}
15
Brent White

Vous pouvez gérer l'événement submit () , qui se produira uniquement pour la soumission de votre formulaire.

Dans cet événement, définissez votre variable indicateur formHasChanged sur false pour permettre au déchargement de continuer. Aussi, juste une suggestion, mais puisque le but de cette variable de drapeau aura changé, vous voudrez peut-être la renommer quelque chose comme 'warnBeforeUnload'

$(document).submit(function(){
    warnBeforeUnload = false;
});
10
Derek Hunziker

Je cherchais une meilleure solution à cela. Ce que nous voulons, c'est simplement exclure un ou plusieurs déclencheurs de la création de notre "Êtes-vous sûr?" boite de dialogue. Nous ne devons donc pas créer de plus en plus de solutions de contournement pour de plus en plus d'effets secondaires. Que faire si le formulaire est soumis sans un événement click du bouton d'envoi? Que se passe-t-il si notre gestionnaire de clics supprime le statut isDirty mais que le formulaire de soumission est par la suite bloqué par la suite? Bien sûr, nous pouvons changer le comportement de nos déclencheurs, mais le bon endroit serait la logique gérant la boîte de dialogue. La liaison à l'événement submit du formulaire au lieu de la liaison à l'événement click du bouton d'envoi est un avantage des réponses dans ce fil par rapport à d'autres que j'ai vues auparavant, mais cette IMHO corrige simplement la mauvaise approche.

Après quelques recherches dans l'objet événement de l'événement onbeforeunload, j'ai trouvé la propriété .target.activeElement, Qui contient l'élément, qui a déclenché l'événement à l'origine. Donc, oui, c'est le bouton ou le lien ou tout ce sur quoi nous avons cliqué (ou rien du tout, si le navigateur lui-même s'est éloigné). Notre "Êtes-vous sûr?" la logique de dialogue se réduit alors aux deux composants suivants:

  1. La gestion de isDirty du formulaire:

    $('form.pleaseSave').on('change', function() {
      $(this).addClass('isDirty');
    });
    
  2. Le message "Êtes-vous sûr?" logique de dialogue:

    $(window).on('beforeunload', function(event) {
      // if form is dirty and trigger doesn't have a ignorePleaseSave class
      if ($('form.pleaseSave').hasClass('isDirty')
          && !$(event.target.activeElement).hasClass('ignorePleaseSave')) {
        return "Are you sure?"
      }
      // special hint: returning nothing doesn't summon a dialog box
    });
    

C'est simplement comme ça. Aucune solution de contournement nécessaire. Donnez simplement aux déclencheurs (soumettre et autres boutons d'action) une classe ignorePleaseSave et le formulaire que nous voulons pour que la boîte de dialogue soit appliquée à une classe pleaseSave. Toutes les autres raisons de décharger la page invoquent alors notre "Êtes-vous sûr?" dialogue.

P.S. J'utilise jQuery ici, mais je pense que la propriété .target.activeElement Est également disponible en JavaScript simple.

2
spackmat