Fixing addEventListener not working with beforeunload

Guide to Fixing why addEventListener not working with beforeunload event!

Jul 7, 2023 | Read time 10 minutes

πŸ”” Table of contents

Introduction

The reason why addEventListener not working with beforeunload can be due to:

  1. Using β€œonbeforeunload” instead of β€œbeforeunload” - and check for any typos!
  2. The user have not interacted with the page - sticky activation
  3. You are not using the event.returnValue property
  4. You are not using the event.preventDefault() function
  5. There are browser compatibility issues

Recently I was working on a Vue project and had the requirement to display a message to the user before they leave the page.

I wanted to also save the user’s form data when they leave the page also - just to make sure that they do not lose any of their data.

However, I found that using the β€œbeforeunload” was not working.

⭐ Note: The onbeforeunload event is a special type of event in JavaScript that is triggered when the user is about to leave the current webpage. This event is often used to warn users about unsaved changes or other important state that could be lost if they navigate away.

In this post I will detail over the steps and checklist I took to troubleshoot and fix this error.

1. Using β€œonbeforeunload” instead of β€œbeforeunload” - and check for any typos!

A common mistake is to use the β€œonbeforeunload” when calling the addEventListener:

  

// ❌ This will not work 
window.addEventListener('onbeforeunload', function (event) {
    // Your code here...
});

The proper way is to use β€œbeforeunload” (eg no - β€œon” prefix)

  

window.addEventListener('beforeunload', function (event) {
    // Your code here...
});

Keep in mind that addEventListener is case-sensitive on the event types that it accepts. So only β€œbeforeunload” (all lowercase will work) and NOT β€œBeforeUnload” (having capitals)

πŸ‘‰ Difference between onbeforeunload and beforeunload

So what is the difference between β€œonbeforeunload” and β€œbeforeunload”??

They are pretty much the same - just different ways of registering the event handler in JavaScript.

If you are dealing with β€œonbeforeunload” - you can set the handler on objects like β€œwindow”:

  

window.onbeforeunload = function(e) {
  return 'Are you sure you want to leave?';
};

If you are using β€œbeforeunload”, then it is a string (case-sensitive) that is passed to the addEventListener function:

  

window.addEventListener('beforeunload', function(e) {
  e.preventDefault();
  e.returnValue = 'Are you sure you want to leave?';
});

In terms of functionality, the should be able to fire when the document and its resources are about to be unloaded.

Using addEventListener with β€˜beforeunload’ is generally considered better practice because it allows you to add multiple event handlers for the same event, whereas onbeforeunload only allows one.

Another disadvantage of using β€œonbeforeunload” is that if you assign a new function to it - the old handler will be overwritten.

2. The user have not interacted with the page - sticky activation

One thing to keep in mind is that the beforeunload event will only be triggered when sticky activation is true.

So what the heck is sticky activation??

Its also known as β€œsticky user activation,” is a state of a window that signifies a user has interacted with the page through actions like:

  • clicking a button,
  • moving the mouse,
  • using a menu, or other user interactions.

A page is deemed β€œuser activated” if a user is currently interacting with it or has performed a touch, pointer, or keyboard interaction since the page was loaded.

Sticky user activation remains set for the entire session once it’s activated.

So it may be that your code is correct, but the beforeunload might seem like its not working because the user have not done anything with the page!

Additionally, uou can check if sticky activation is on by checking the UserActivation.hasBeenActive property!

  

if (navigator.userActivation.hasBeenActive) {
  // proceed with auto-playing an animation, for example
}

3. You are not using the event.returnValue property

Generally, you will need to supply a value for the event.returnValue property. The HTML standard does not require this, but some browsers seem to expect it.

Here’s an example:

  

window.addEventListener('beforeunload', function (event) {
    event.preventDefault(); // If you want to prevent the default action
    event.returnValue = 'Do you want to leave?'; // This will cause a confirmation dialog to appear
});

Now originally, the string you set for the β€œreturnValue” is what is going to be displayed in the dialog. However with more modern browsers this is just replaced by a standard message.

πŸ‘‰ History of beforeunload event

Over the years theres been a few changes to the β€œbeforeunload” and how that is implemented with browsers.

In 2014, the general approach would be:

  

window.addEventListener("beforeunload", function (e) {
  var confirmationMessage = "Do you want to leave?";

  (e || window.event).returnValue = confirmationMessage;     //Gecko + IE
  return confirmationMessage;                                //Webkit, Safari, Chrome etc.
});

Now with more modern browsers and updated HTML standard, the approach to maximize browser compatibility is:

  

window.addEventListener('beforeunload', (event) => {
  // Cancel the event as stated by the standard.
  event.preventDefault();
  // Chrome requires returnValue to be set.
  event.returnValue = '';
});

We do need to set a meaningful message text for the beforeunload event, as it will lead to inconsistent user experiences across different browsers.

  • You can use event = event || window.event to ensure that the event object is defined.
  • Use event.preventDefault(), but first check if preventDefault is defined.
  • Set event.returnValue = '' and return '' to ensure the beforeunload event works correctly.

4. You are not using the event.preventDefault() function

According to the specification, to show the confirmation dialog an event handler should call preventDefault() on the event.

The preventDefault() method of the Event interface tells the user agent that if the event does not get explicitly handled, its default action should not be taken as it normally would be.

5. There are browser compatibility issues

The HTML specification advises using the Event.preventDefault() method instead of Event.returnValue to prompt the user, but not all browsers support this yet.

  • If this event returns a value other than null or undefined, or if the returnValue property is set to such a value, the user will be prompted to confirm the page unload.

  • In older browsers, the return value of the event is displayed in this dialog. However, since Firefox 44, Chrome 51, Opera 38, and Safari 9.1, a generic string not controlled by the webpage is shown instead.

  • Firefox displays: β€œThis page is asking you to confirm that you want to leave - data you have entered may not be saved.”

  • Chrome displays: β€œDo you want to leave the site? Changes you made may not be saved.”

  • Some browsers may ignore calls to window.alert(), window.confirm(), and window.prompt() during this event.

  • Certain browsers ignore the result of the event and do not ask the user for confirmation at all, automatically unloading the document. Firefox has a switch named dom.disable_beforeunload in about:config to enable this behavior.

  • As of Chrome 60, the confirmation will be skipped if the user has not performed a gesture in the frame or page since it was loaded. Pressing F5 in the page counts as user interaction, but mouse-clicking the refresh arrow or pressing F5 with Chrome DevTools focused does not count as user interaction (as of Chrome 81).

πŸ‘‰ TIP: Using the onbeforeunload in HTML

One thing that I found works the best for cross browser compatibility is to use the β€œonbeforeunload” attribute in HTML:

  

<body onbeforeunload="alert('Goodbye')">

Keep in mind that the onbeforeunload event can be invoked by:

  • Navigating to another page directly in the browser or via a link.
  • Closing the current browser window or tab page.
  • Reloading the current page.
  • Manipulating the URL of the currently loaded page through the location object from JavaScript.
  • Invoking the window.navigate method.
  • Invoking the window.open or the document.open method to open a document in the same window.

Summary

Generally, addEventListener is not working with beforeunload can be due to multiple reasons.

This can mean that you are using onbeforeunload instead of β€œbeforeunload”. Also make sure that there are no typos since addEventListener event type is case-sensitive.

Also check for the following:

  • that the user have interacted with the page (sticky activation)
  • you have set a value for event.returnValue
  • you have called the event.preventDefault()
  • browser compatibility issues with beforeunload - the HTML standard is not fully implemented by modern browsers

πŸ‘‹ About the Author

G'day! I am Huy a software engineer based in Australia. I have been creating design-centered software for the last 10 years both professionally and as a passion.

My aim to share what I have learnt with you! (and to help me remember πŸ˜…)

Follow along on Twitter , GitHub and YouTube