Home > Enterprise >  FormData object is empty when using vue @submit directive
FormData object is empty when using vue @submit directive

Time:02-03

I came across some weird edge case and I narrowed it down to a solution. I created a form with vue and empty strings were being sent down to the server. I narrowed it down to the @submit directive. If I write form.addEventListener('submit') everything works as it should but with the @submit directive it does not work.

The solution is to use the addEventListener method but I'm not sure if I did something wrong here or if this is a bug with vue's v-on directive

Runnable example: https://stackblitz.com/edit/web-platform-izreva?file=index.html

NOTE: I know about the form data object and how to view it with

for (const [key, value] of formData.entries()) {
  console.log(`${key}: ${value})
}

In the below snippet if you uncomment the code then it works with addEventListener.

const form = document.querySelector('#test-form')

const app = Vue.createApp({
  name: 'test app',
  methods: {
    test(e) {
      e.preventDefault()
      console.log(e)

      const formData = new FormData(form)
      for (const [key, value] of formData.entries()) {
        console.log(`${key}: ${value}`)
      }
    }
  }
}).mount('#app-main')

// const form = document.querySelector('#test-form')
// form.addEventListener('submit', e => {
//   e.preventDefault()

//   const formData = new FormData(form)
//   for (const [key, value] of formData.entries()) {
//     console.log(`${key}: ${value}`)
//   }
// })
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Home</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <script src="https://unpkg.com/[email protected]/dist/vue.global.js" defer></script>
  </head>
  <body>
    <h1>app</h1>
    <div id="app-main">
      <form @submit="test" id="test-form">
        <input type="text" name="foo">
        <button type="submit">submit</button>
      </form>
    </div>

    <script src="./index.js" defer></script>
  </body>
</html>

CodePudding user response:

I imagine this is an issue with how the CDN version of Vue parses a template from existing HTML.

Each element is replaced with the Vue compiled element equivalent.

The form you captured at the start is no longer the one emitting the submit event. You can easily check this by comparing form === e.target.

If you use the following it works as expected.

const formData = new FormData(e.target);

In short, you're doing things in a very non-Vue way so it's little surprise you've encountered some friction.

  • Related