Handling form submissions in Vue.js before navigating away from the current route

As a newcomer to VueJs, I am facing a problem with creating a form. My goal is to display an alert dialog with the message "you might lose the data, please save the data before you leave," and upon clicking 'yes', the form should be submitted and the route should change.

I understand that this can be achieved using beforeRouteLeave(to, from, next), but how can I submit the form before leaving the route when clicking 'yes' in the alert box?

https://i.sstatic.net/rw1f1.png In the image above, my current route is /create.

handleArticleSubmit() {
    // Collect form data
    let formData = new FormData();

    // Start Button Loading
    this.isSubmittingArticle = true;
    axios
      .post("/articles", formData, {
        headers: {
          "Content-Type": "multipart/form-data"
        }
      })
      .then(res => {
        // Stop button loading
        this.isSubmittingArticle = false;
        // Show alert message
        this.snackbar = {
          isVisible: true,
          color: "success",
          text: "Article submitted successfully"
        };

      })
      .catch(error => {
        // Stop button loading
        this.isSubmittingArticle = false;
        // Show alert
          // Show alert message
          this.snackbar = {
            isVisible: true,
            color: "error",
            text: error
          };
        }
      });
  }
},

The code mentioned above saves the article, and I aim to change the route only if the form submits with all validations (such as blank fields or numbers). If not, the route should not change. Thank you for your help.

beforeRouteLeave(to, from, next) {
  const answer = window.confirm(
    "You might lose the data, please save it before leaving."
  );
  if (answer) {
    this.handleArticleSaveDraft();
    next();
  } else {
    next(false);
}

Thank you.

Answer №1

Revised Response

Please take these into consideration:

  1. Ensure that the handleArticleSubmit method is promisified
  2. Make beforeRouteLeave asynchronous
  3. Utilize try/cache to validate the promise. In case of rejection (error in form), ensure page remains unchanged, and optional error logging can be included.

Refer below for implementation details:


methods: {
    handleArticleSubmit() {
        return new Promise((resolve, reject) => {   // 1. Promisify the method                  
            let formData = new FormData() 
            this.isSubmittingArticle = true 
            axios
            .post("/articles", formData, {
                headers: {
                    "Content-Type": "multipart/form-data"
                }
            })
            .then(res => {        
                this.isSubmittingArticle = false         
                this.snackbar = { 
                    isVisible: true,
                    color: "success",
                    text: "Article submitted successfully"
                }
                resolve() // Resolve the promise (all good)
            })
            .catch(error => {        
                this.isSubmittingArticle = false         
                this.snackbar = { // Display alert message
                    isVisible: true,
                    color: "error",
                    text: error
                }   
                reject(error) // Reject if error occurs
            })
        })
    }
},
async beforeRouteLeave(to, from, next) { // 2. Make this asynchronous
    let answer = window.confirm("you might lose data, please save before leaving.")
    if (answer) {
        // 3. Try/catch block to confirm resolution
        try{ 
            await this.handleArticleSubmit() 
            // Resolved
            next() 
        } catch (err) { // Rejected
            next(false)
            log(err)
        }                
    } else {
        next(false)
    }
}

Prior Explanation

This concept is explicitly detailed in the Navigation Guards as Leave Guard within Vue Router documentation.

beforeRouteLeave (to, from, next) {
  const answer = window.confirm('you might lose data, please save before you leave.')
  if (answer) {
    this.submit() // Submit your form as required
    next()
  } else {
    next(false)
  }
}

Alternatively, if utilizing a custom modal system, ensure it is asynchronous and returns a promise:

async beforeRouteLeave (to, from, next) {
  const answer = await this.openModal()
  if (answer) {
    this.submit() // Submit form accordingly
    next()
  } else {
    next(false)
  }
}

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

Issue with Ref when used in a distinct HTML template

I have encountered a frustrating issue with my simple Vue project. When I separate the template and code into individual files, the ref stops working and I end up with an undefined value in the HTML template. This scenario works fine: map.component.vue ...

React Native: Struggling with Button Styling

I am relatively new to React Native, although I have experience with React in my professional work. I'm finding that applying styles to components in React Native is a bit different than what I'm used to. Specifically, I am struggling to apply s ...

Working with Vue: Nesting arrays through callback functions

I am currently converting images into base64 format within a component and attempting to insert the objects into an array. Essentially, it's a collection of items where each item has a set of images associated with it. <base64 :index="index" :mul ...

"Step-by-step guide to updating user information in MongoDB with the help of node.js

I have been working on a basic express app with MongoDB integration, allowing users to register, log in, and log out successfully. However, I am facing an issue when attempting to implement the functionality to edit user data. The code runs without any err ...

Utilizing AngularJS for Converting Date Formats from JSON and HTML Elements

So I have this controller set up. function TestCtrl($scope) { var contentFromJson = 'Hi! this is <b>Bold</b> and <i>Italic</i>'; var dateFromJson = '/Date(1394526738123)/'; $scope.Date = dateFromJso ...

Alter the truth value of an item contained within an array

Embarking on my JavaScript journey, so please bear with me as I'm just getting started :) I am working on a small app where the images on the left side are stored in an array. When a user clicks on one of them, I want to change its height and also tog ...

What is the best method for storing dynamic values and attribute labels in a state within a React.js application?

I am currently working with react js. On my single product page, I have an array of objects called attributes that I need to display in the user interface. Here is a preview of how it looks: https://i.sstatic.net/GttrD.png My goal is to retrieve and stor ...

How can a component receive data from its parent element?

While diving into Vue.js, I encountered a puzzling issue - why isn't <li>{{task.body}}</li> appearing on the screen? I've crafted a <tasks v-for="task in tasks"></tasks> component that requires access to data from its par ...

Troubleshooting the display of API-generated lists in Angular 8

I am encountering an issue in Angular 8 when trying to display my list on a page. Below is the code from my proposal-component.ts file: import { Component, OnInit, Input } from "@angular/core"; import { ActivatedRoute, Params } from "@angular/router"; imp ...

Utilizing the .map() function to retrieve an object from an array without a key

Exploring Dialogflow, I aim to retrieve the speech value for the object in the messages array that lacks a platform key: "messages": [ { "type": 0, "platform": "skype", "speech": "FOO" }, { "type": 0, "platform": ...

Translate data from two "contact form 7" date fields into JavaScript/jQuery to display the date range between them

NEW UPDATE: I was able to get it working, but the code is a bit messy. If anyone can help me clean it up, I would greatly appreciate it. <div class="column one-fourth" id="date-start">[date* date-start date-format:dd/mm/yy min:today+1days placeholde ...

Error retrieving data from the ngresource properties resource

In the code snippet below, I have a simple factory that requests a json object containing location information. The requests are successful and the data is present in the object. However, there seems to be a scope problem as I am unable to access the prope ...

What could be the reason for my onChange event not functioning properly?

The issue I'm experiencing involves my onchange event not properly copying the text from the current span to the hidden field. Any ideas on why this might be happening? Check out my code at this link. ...

the width of the table body is narrower than the table itself

I'm working on a table that has a fixed first column and needs to be vertically scrollable. I'm almost there with my CSS code, but the table rows are not as wide as the columns and I'm unsure why this is happening. .table th:first-child, ...

Tips for managing the sequence of chosen items

Currently, I am utilizing the react-dropdown-tree-select component in my project. I have a question regarding changing the order of selected items. The current default behavior is for the selected item order to match the data list order. However, I woul ...

Tips for sending query parameters with axios

I'm facing an issue with sending a request to http://localhost:5000/trackers/{{id}}. Despite trying to pass parameters through axios, the API is only receiving requests at http://localhost:5000/trackers/. How can I resolve this problem? Below is my A ...

Setting properties on functions and defining their prototype

My task involves working on the following block of code: function Vector(x, y) { this.x = x || 0; this.y = y || 0; } Vector.add = function(a, b) { return new Vector(a.x + b.x, a.y + b.y); }; Vector.sub = function(a, b) { return new Vecto ...

Angular can help you easily convert numbers into a money format

I need assistance in converting a number to Indian currency format. Currently, I have attempted the following: http://plnkr.co/edit/lVJGXyuX0BMvB9QUL5zS?p=preview function formatMoney(credits) { console.log(credits+'credits'); var last ...

Creating flexible items with a 1:1 ratio and ensuring that the padding on the left and right of the flex container remains consistent

Whenever I adjust the size of the window, https://i.sstatic.net/Fm3d1.png the flex-container ends up with uneven padding on the left and right, which is less than ideal. So, I am looking for a way to allow the flex-item to resize when the window size c ...

Please do not exceed two words in the input field

I need to restrict the input field to only allow up to two words to be entered. It's not about the number of characters, but rather the number of words. Can this restriction be achieved using jQuery Validation? If not, is there a way to implement it u ...