@rthaut looks like doing the submission using just js without alpine solved everything.
I’m not particularly good with js so just in case someone else is in the same boat that I was, here are a couple of reference links I used.
JS form tutorial
Helpful community forum post
Youtube vid specifically for netlify and js forms The video is linked in the community post but I missed it at first.
And if you just wanted to see my js and html here it is. I’m using tailwind if the classes look unfamiliar.
js
window.addEventListener("load", function () {
// get the form
const form = document.getElementById("work-contact");
// get the success message
const successMsg = document.getElementById("showSuccessMessage");
// get all the form elements
let userName = form.elements["name"];
let userEmail = form.elements["email"];
let userMessage = form.elements["message"];
// set up required fields
const requiredFields = [
{ input: userName, message: "Name is required" },
{ input: userEmail, message: "Email is required" },
{ input: userMessage, message: "Message is required" },
];
function error(input, message) {
// get error message template
var et = input.previousElementSibling;
// change class name so error message template shows
et.classList.remove("h-0", "opacity-0");
et.classList.add("h-100", "opacity-100");
// get the span in the error template (et)
const errorMsg = et.querySelector("span.errormsg");
// add inner text into the span
errorMsg.innerText = message;
return false;
}
function success(input) {
// get error message template
var et = input.previousElementSibling;
// change class name so error message template is hidden
et.classList.remove("h-100", "opacity-100");
et.classList.add("h-0", "opacity-0");
// get the span in the error template (et)
const errorMsg = et.querySelector("span.errormsg");
// remove text message
errorMsg.innerText = "";
return true;
}
function requireValue(input, message) {
// check if inputs are blank
return input.value.trim() === "" ? error(input, message) : success(input);
}
function validateEmail(input) {
// create regex to check if valid email pattern
const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
// text regex against input value
return re.test(input.value.trim())
? success(input)
: error(input, "Invalid email format");
}
form.addEventListener("submit", (event) => {
// prevent default form submit action
event.preventDefault();
// bool for async actions
let valid = true;
// create async function to perform actions in sequence
async function validate() {
// loop over required fields object and check if inputs are blank
requiredFields.forEach((input) => {
valid = requireValue(input.input, input.message);
});
}
validate()
.then(() => {
if (valid) {
// if no inputs are blank check if email field has a valid pattern
valid = validateEmail(userEmail);
}
})
.then(() => {
if (valid) {
// if no inputs are blank and email is valid
//show success message
successMsg.classList.remove("h-0", "opacity-0");
successMsg.classList.add("h-auto", "opacity-100");
// hide form
form.classList.add("h-0", "opacity-0");
// get formData
const formData = new FormData(form);
// post form data
fetch(form.getAttribute("action"), {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
},
body: new URLSearchParams(formData).toString(),
}).then((res) => {
if (res) {
// reset form fields
form.reset();
console.log(res.ok);
}
});
}
});
});
});
html
<form id="work-contact" class="flex flex-col w-full transition duration-200 ease-in-out" name="work-contact" data-netlify="true" action="/#contact-form">
<input type="hidden" name="work-type" value="{{.section}} enquiry">
<label class="uppercase text-sm pb-2" for="name">Name</label>
<div class="h-0 transition duration-200 ease-in-out">
<div class="border border-l-4 border-pink-500 px-4 py-2 mb-4 rounded-lg">
<svg class="w-6 h-6 text-pink-500 fill-current float-left mr-1"
style="top: 10px; right: 12px" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24">
<path
d="M11.953,2C6.465,2,2,6.486,2,12s4.486,10,10,10s10-4.486,10-10S17.493,2,11.953,2z M13,17h-2v-2h2V17z M13,13h-2V7h2V13z" />
</svg>
<span class="errormsg text-pink-500 text-sm block"></span>
</div>
</div>
<input class="bg-white border border-gray-400 focus:outline-none focus:border-greenblue-500 text-base px-4 py-3 mb-4 rounded-lg relative" placeholder="Name*" name="name" type="text">
<label class="uppercase text-sm pb-2" for="email">Email</label>
<div class="h-0 opacity-0 transition duration-200 ease-in-out">
<div class="border border-l-4 border-pink-500 px-4 py-2 mb-4 rounded-lg">
<svg class="w-6 h-6 text-pink-500 fill-current float-left mr-1"
style="top: 10px; right: 12px" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24">
<path
d="M11.953,2C6.465,2,2,6.486,2,12s4.486,10,10,10s10-4.486,10-10S17.493,2,11.953,2z M13,17h-2v-2h2V17z M13,13h-2V7h2V13z" />
</svg>
<span class="errormsg text-pink-500 text-sm block"></span>
</div>
</div>
<input class="bg-white border border-gray-400 focus:outline-none focus:border-greenblue-500 text-base px-4 py-3 mb-4 rounded-lg relative" placeholder="Email*" name="email" type="text">
<label class="uppercase text-sm pb-2" for="message">Project details</label>
<div class="h-0 opacity-0 transition duration-200 ease-in-out">
<div class="border border-l-4 border-pink-500 px-4 py-2 mb-4 rounded-lg">
<svg class="w-6 h-6 text-pink-500 fill-current float-left mr-1"
style="top: 10px; right: 12px" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24">
<path
d="M11.953,2C6.465,2,2,6.486,2,12s4.486,10,10,10s10-4.486,10-10S17.493,2,11.953,2z M13,17h-2v-2h2V17z M13,13h-2V7h2V13z" />
</svg>
<span class="errormsg text-pink-500 text-sm block"></span>
</div>
</div>
<textarea class="bg-white border border-gray-400 focus:outline-none focus:border-greenblue-500 text-base px-4 py-3 mb-4 font-sans rounded-lg" placeholder="Tell us about your project" name="message"></textarea>
<button class="p-4 bg-greenblue-500 text-white uppercase hover:bg-greenblue-400 hover:text-white transition ease-in-out duration-200 rounded-lg" type="submit" >
Get in touch <i class="fas fa-arrow-right fa-xs rotate45"></i>
</button>
</form>