Easy steps to prevent window.onbeforeunload from triggering when submitting a form using Vue

Presently, I am utilizing a component named countdowntimer.vue, specifically designed as a countdown timer for an online examination platform. My goal is to implement an onbeforeunload event on the window object while ensuring that the timer automatically submits upon completion without being disrupted by the window event itself. Despite my attempts to integrate this code within the vuejs component, it fails to respond as desired; either hindering the submission process with interruptions or failing to function altogether, allowing any event to navigate away from the page without constraint.

Below is the code snippet depicting the countdown timer:

<template>
    <div>
        <div v-if="finished" v-text="expiredText"></div>

        <div v-else>
            <span>{{ remaining.minutes }} Minutes, </span>
            <span>{{ remaining.seconds }} Seconds</span>
            left...
        </div>
    </div>
</template>

....

Despite various trials of setting the method as a computed property and employing different if statements as watchers, the method does not yield the expected outcomes as previously mentioned.

The blade template in which the code is implemented is presented below:

@extends('layouts.app')

@section('content')
   ...
    </div>
@endsection

.....

Upon observation, there appears to be a script tag located outside of the @endsection block. It has been discerned that this placement fails to establish a connection with elements from the blade template. Attempts were made to access the form object similarly done in the vue component. However, this resulted in a null or undefined response - rendering it impossible to attach an event listener. Interestingly, executing the same logic within the browser console produced the anticipated results. The assigned onsubmit="" event intended for the form failed to reach the underlying script tags, leading to an unaltered value in the submitForm variable. Moreover, manually clicking the submit button succeeded in triggering the function clicked(). Under these circumstances, confusion ensues regarding the feasibility of achieving the desired outcome solely through vue. Additionally, the nonfunctional nature of the onsubmit="" event raises uncertainties. Moving the script tags inside the @section could potentially prompt errors from vue. Hence, any recommendations or insights on resolving these issues would be greatly appreciated.

Answer №1

To begin with, ensure that you pass a method reference to beforeunload, not the result of calling that method. Remove the ():

created () {
    this.refreshEverySecond();
    document.addEventListener('beforeunload', this.redirect); // not this.redirect()
},

A simple solution to toggle the handler on and off is to use a flag:

data () {
    return {
        limiter: this.until * 10000
        preventSubmit: true
    };
},

In your methods, update or utilize that flag accordingly:

methods: {
    // ...
    timeUp() {
        this.preventSubmit = false; // ALLOW redirect now

        const form = document.querySelector('[data-form-submit]');
        const radios = document.querySelectorAll('input[type=radio]');
        radios.forEach(radio => radio.style.display = 'none');
        form.submit(function(e) {
            console.log(e);
        });
    },
    redirect () {
        if (this.preventSubmit) {
           // implement steps to prevent submit
        }
    }
},

Another Approach

Alternatively, you can remove the listener:

created () {
    this.refreshEverySecond();
    document.addEventListener('beforeunload', this.redirect); // not this.redirect()
},

And in your methods:

methods: {
    // ...
    timeUp() {
        document.removeEventListener('beforeunload', this.redirect);
        // ...

I believe using the flag alternative is more reliable.


Proper Handling of beforeunload

As per feedback, here's a demo showcasing how it could function.

You can view the JSFiddle DEMO here or see the demonstration below.

new Vue({
  el: '#app',
  data: {
    preventSubmit : true
  },
  mounted () {
    window.addEventListener("beforeunload", this.redirect);
},
  methods: {
  redirect(event) {
    if (this.preventSubmit) {
      var confirmationMessage = "\o/";
      event.returnValue = confirmationMessage;  
      return confirmationMessage;
      }
    }
  }
})
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <p>preventSubmit ? {{ preventSubmit  }}</p>
  <button @click="preventSubmit = !preventSubmit ">Toggle preventSubmit </button>
</div>
<br>
<a href="/somewhere-else">click to try to navigate away</a>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to adjust the height pixel value in my code so it can be dynamic?

I have created a simple script that allows selected objects to fade in as the user scrolls down. However, my issue is that this script is quite rigid. If I were to apply it to 20 different objects, for example, I would need to manually adjust the height ea ...

Unusual scroll bar movements when using jQuery validation

When I click the Add Dependent link button, I wanted the scroll bar to automatically scroll to the bottom, and it does just that. However, there is a small issue after the postback where the text "Please fix the following problems:" briefly appears, even t ...

The code encountered an error with message TS2345 stating that the argument type '(a: Test, b: Test) => boolean | 1' cannot be assigned to a parameter type of '(a: Test, b: Test) => number'

Apologies for the lengthy subject, but I am having trouble understanding the response. Here is my code snippet: this.rezerwacjeFilteredByseaarchInput.sort(function (a, b) { if (a[5]===null) { // console.log(a[5]); return 1; } ...

What is the best practice for preloading route data before navigating to the route?

When preparing to render a page for a specific route, my goal is to fetch the necessary data synchronously first. Ideally, I prefer to handle the data fetching within the page component, but I am open to doing it in the router files as well. I have experim ...

When setting up a new nodejs/express project, I encountered an issue where the fresh installation would fail

After setting up node and express on my new development server, I created a test application by running the command below: dev-server15:/var/www# express mytest create : mytest create : mytest/package.json create : mytest/app.js ... The npm ...

What is the process for submitting a form on consecutive URLs?

I have a form that requires input for settings and includes two buttons: one to save the form and another to both save and execute the settings. <form method="post" action="/settings/{{id}}/save"> <!-- input fields --> ...

Leveraging Multiple MongoDB Databases in Meteor.js

Can 2 Meteor.Collections fetch data from separate MongoDB database servers? Dogs = Meteor.Collection('dogs') // mongodb://192.168.1.123:27017/dogs Cats = Meteor.Collection('cats') // mongodb://192.168.1.124:27017/cats ...

Is it possible to extract data from a table by adjusting Javascript in the inspector tool? The page is only showing today's data, but I'm interested in retrieving historical data by going back

My Desired Action: I am interested in extracting data from the 2nd and 3rd tables on this page. However, the data displayed is specific to the current 'day'. I wish to access readings from September 1st and import them into a Google Sheet. Speci ...

Changing the way users are linked in a post using HTML tags (VUE-NODE)

I am trying to modify a body property that includes usernames @username1 and @username2. Is it feasible to use regex to transform these nicknames into router links? The desired output should be like this (with the @ removed in the link profile) <router ...

The output from the Compute function is not showing up in the TextBox as expected

I'm currently working on an HTML page that contains two textboxes and a button. I've created a Compute function to display the result in one of the textboxes, but unfortunately, it's not functioning as expected. No alerts are appearing on th ...

A guide on incorporating a JavaScript plugin using Vue.use() into a TypeScript project equipped with typings

Currently, I am facing an issue while attempting to integrate Semantic-UI-Vue into my Vue project. Upon trying to execute Vue.use(SuiVue), the following error message is displayed: Argument of type 'typeof import("semantic-ui-vue")' is not ass ...

What is the process for linking read-only methods to Redux object instances?

Let's say I have a "user" object stored in redux, with fields for first name and last name (interface User { firstName : string, lastName : string} if using typescript). After retrieving a user from redux, I want to obtain the full name of the user by ...

What could be preventing me from successfully calling the JavaScript AJAX function in this particular situation?

Here is my code snippet from a smarty template: <form name="transaction_form" id="transaction_form"> <table class="trnsction_details" width="100%" cellpadding="5" > <tbody> <tr> ...

What is the reason objects cannot be compared in JavaScript?

I have a straightforward code snippet here. Its purpose is to authenticate the user against the author of the post and grant the authenticated user access to edit the post. exports.edit = function(req, res){ Post.findById(req.params.post_id, function ...

React Router's default component for nested routes

In React Router, I am facing a challenge with nested Routes <Route path='about' component={{main: About, header: Header}}> <Route path='team' component={Team} /> </Route> Currently, the Team component is displayed ...

Protractor is able to achieve successful test results without actually executing the tests

SYMPTOMS When running Protractor, the tests pass successfully, but the pages do not load. Instead, they appear blank with "data:text/html" in the address bar (refer to the screenshot). Although the tests show as passed, there are 0 assertions being made. ...

Tips for organizing and concealing images within a Div for seamless transitions (no need for floats)

Currently, I am working on a grid layout for my website. My goal is to have 9 images load quickly, and then once the page has loaded, I want to fetch additional images, insert them into the image containers, and animate between them. While I understand how ...

Issue: The specific module is unable to be located, specifically on the Heroku platform

While my application performs well locally and on a Travis CI build server, it encounters issues when deployed on Heroku. The error message Error: Cannot find module is displayed, leading to app crashes. Here are some details about the npm module: It r ...

restrict the maximum character count in regex

The string can consist of a single number or multiple numbers separated by "-", but the total character count must not exceed 6. Examples of valid strings 5 55-33 4444-1 1-4444 666666 Examples of invalid strings -3 6666- 5555-6666 My initial regex / ...

Error message: Attempting to access the 'load' property of a null value

Currently, I'm working on a code that is meant to automatically refresh the viewer count every 10 seconds. However, I've encountered an issue where nothing is being outputted, and in the console, it shows cannot read property 'load' of ...