0

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>
8
  • Are you sure the testSubmit() function is running? Commented Feb 3, 2023 at 0:07
  • Yes I tested everything in the console. Commented Feb 3, 2023 at 0:10
  • 1
    Is the FormData empty (no keys), or does it have keys with empty values for each? Commented Feb 3, 2023 at 0:12
  • Have you checked, on the failing case, if there are errors in the console? Commented Feb 3, 2023 at 0:12
  • 1
    What happens if you do console.log(document.querySelector("[name='foo']").value); in testSubmit()? Commented Feb 3, 2023 at 0:29

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Yea that fixed it, can you briefly elaborate on this a bit more? Vue looks at the static html and creates it's own copy and that copy is what emits a submit event correct? Is there a more declarative way of doing this if I am stuck using static html? Perhaps using a template ref? I am using shopify and that is why I gotta import vue via cdn
@dbzx10299 that sounds about right. TBH I haven't looked very closely at the static HTML compiler. A declarative version might be to use refs to keep track of your elements within the Vue component context. That being said, I see no problem using the event target

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.