I came across some weird edge case and I narrowed it down to a solution. I created a form with vue and I thought that vue was causing this weird behavior but it was the fact that the script had a type="module"
attribute.
When I moved the script into it’s own file and added a defer attribute then everything worked fine. My question is why. I know there are differences with type module and a normal script tag with a defer attribute but I’m not clear on why the FormData object is empty when using an inline script with type module.
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})
}
The below code was sending empty string to my backend express server. I noted that on the frontend the testSubmit
function was showing no value from the console.log.
<!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="testSubmit($event)" id="test-form">
<input type="text" name="foo">
<button type="submit">submit</button>
</form>
</div>
<!-- <script src="./index.js" defer></script> -->
<script type="module">
const form = document.querySelector('#test-form')
const app = Vue.createApp({
name: 'test app',
data() {
return {
foo: 'foo'
}
},
methods: {
testSubmit(e) {
e.preventDefault()
/** nothing was logged here
* and empty strings were showing up on the server
*/
const formData = new FormData(form)
for (const [key, value] of formData.entries()) {
console.log(`${key}: ${value}`)
}
fetch('/form', {
method: 'POST',
body: new FormData(form)
})
}
}
}).mount('#app-main')
</script>
</body>
</html>
If I change the code to this
<!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="testSubmit($event)" id="test-form">
<input type="text" name="foo">
<button type="submit">submit</button>
</form>
</div>
<!-- Now everything works and the FormData object contains values
The values are also showing up on the server end
-->
<script src="./index.js" defer></script>
</body>
</html>