I am using window.onbeforeunload to prevent the user from navigating away after changing values on a form. This is working fine, except it also shows the warning when the user submits the form (not desired).
How can I do this without showing the warning when the form submits?
Current code:
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;
}
}
});
The onbeforeunload event occurs when the document is about to be unloaded. This event allows you to display a message in a confirmation dialog box to inform the user whether he/she wants to stay or leave the current page. The default message that appears in the confirmation box, is different in different browsers.
Prototype: Whereas unload is a normal event that inherits from Event , beforeunload has its own prototype, BeforeUnloadEvent .
Deprecated. Not for use in new websites.
Using the form's submit event to set a flag might work for you.
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; }); });
you could use .on() to bind onbeforeunload and then use .off() to unbind it in form submission
$(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'); }); }
You can handle the submit() event, which will occur only for your form submission.
Within that event, set your flag variable formHasChanged
to false to allow the unload to proceed. Also, just a suggestion, but since the purpose of that flag variable will have changed, so you may want to rename it something like 'warnBeforeUnload'
$(document).submit(function(){
warnBeforeUnload = false;
});
I was looking for a better solution to this. What we want is simply exclude one or more triggers from creating our "Are you sure?" dialog box. So we shouldn't create more and more workarounds for more and more side effects. What if the form is submitted without a click
event of the submit button? What if our click-handler removes the isDirty
status but then the form-submit is otherwise blocked afterwards? Sure we can change the behaviour of our triggers, but the right place would be the logic handling the dialog. Binding to the form's submit
event instead of binding to the submit button's click
event is an advantage of the answers in this thread above some others i saw before, but this IMHO just fixes the wrong approach.
After some digging in the event object of the onbeforeunload
event I found the .target.activeElement
property, which holds the element, which triggered the event originally. So, yay, it is the button or link or whatever we clicked (or nothing at all, if the browser itself navigated away). Our "Are you sure?" dialog logic then reduces itself to the following two components:
The isDirty
handling of the form:
$('form.pleaseSave').on('change', function() {
$(this).addClass('isDirty');
});
The "Are you sure?" dialog logic:
$(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
});
It's simply as that. No workarounds needed. Just give the triggers (submit and other action buttons) an ignorePleaseSave
class and the form we want to get the dialog applied to a pleaseSave
class. All other reasons for unloading the page then summons our "Are you sure?" dialog.
P.S. I am using jQuery here, but I think the .target.activeElement
property is also available in plain JavaScript.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With