How do I trigger a modal with Aplinejs when a user navigates away from the page?

1.9k views Asked by At

I have a Bootstrap modal that needs to be triggered when the user navigates away from the page. In plain JS the solution is to listen for the mouseleave event, check if the user has manually closed the modal before, and if not, show the modal.

document.addEventListener("mouseleave", function (e) {
        if (e.clientY < 0) {
          if (localStorage.getItem('newsLetterSignUp') === null) {
            $('someModal').modal();
          }
        }
      }, false);

I'm trying to achieve the same behaviour with Apline.js.

The first approach was to set the event handler on the modal itself: (I have a custom model CSS class .newsletter-modal instead of Bootstrap's .modal because I want to handle the visibility with Alpine)

<div x-data="newsletter()">
    <div
      x-show="showModal"
      @mouseleave.document="revealModal"
      class="newsletter-modal show fade"
      id="mailingListModal"
      tabindex="-1"
      role="dialog"
      aria-labelledby="mailingListModal"
      aria-hidden="true"
    >
      <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content" @click.away="showModal = false"> [modal content] </div>
      </div>
  </div>

 <--- JS code to handle the modal actions --->
    <script>
    window.newsletter = function() {
      return {
        showModal: true,
        revealModal(e) {
          alert('leave');
          if (e.clientY < 0 && localStorage.getItem('newsLetterSignUp') === null) {
            this.showModal = true;
          }
        },
        closeNewsletterModal() {
          this.showModal = false;
          localStorage.setItem('newsLetterSignUp', JSON.stringify(new Date()));
        }
      }
    }
  </script>
        

My idea was to add the .document property to the @mouseleave event in order to bind it to the document, but this had no effect.

Another approach was to set the @mouseleave event on the , dispatch an event and listen for the event on the modal. But this also did not cause the event to be fired on mouseleave.

1

There are 1 answers

0
SdeWijs On BEST ANSWER

It turned out the issue was not in the event handler or Alpine, but Firefox. In Firefox, the mouseleave event is not triggered when the user navigates the mouse away from the window. The behaviour is explained in this question

So the solution for Firefox was to add an extra event listener that tracks the mouse movement. And trigger as soon as the e.clientY < 10

// HTML
<div x-data="newsletter()" @mouseleave.window="revealModal" @mousemove.document="isUserLeaving"> ... </div>
// JS
isUserLeaving(e) {
   if (e.clientY < 10) {
       this.revealModal();
   }
}