I have a form that almost works. The form is on a protected SSR route with a hidden dummy form so Netlify knows it exists. I have tried so many iterations of fixes that I have found that I am worried that I am going to eat up the rest of the form submissions for the month just fumbling around in the dark. Here is the details on the project:
- The site is here: https://www.guestcrafter.com
- The password to get into the content is: spin1234
- The route that has the ajax form is: https://www.guestcrafter.com/info-we-need
- The route that has the hidden form is: https://www.guestcrafter.com/form/
All the fields submit and post correctly except the file upload. I haven’t been trying to upload big files. I haven’t gotten any errors or feedback from Netlify when I submit. I have some debugging console.log’s happening on the https://www.guestcrafter.com/info-we-need route and I can see that my file input is in the formData.
I’ve made sure my dummy form is perfectly matched up with the actual form… Here is the dummy form:
<script context="module">
export const prerender = true
</script>
<form
action="/form/"
name="info"
data-netlify="true"
hidden
enctype="multipart/form-data"
>
<input type="hidden" name="form-name" value="info" />
<input type="text" required tabindex="0" name="Name" />
<input type="text" required tabindex="0" name="Location" />
<input type="text" required tabindex="0" name="PrimaryURL" />
<input type="text" required tabindex="0" name="SecondaryURL" />
<textarea required tabindex="0" name="Biography" maxlength="1000" />
<textarea required tabindex="0" name="TechSetup" maxlength="500" />
<input type="email" required tabindex="0" name="Email" />
<input type="tel" required tabindex="0" name="Phone" />
<input type="file" tabindex="0" name="Picture" accept=".png, .jpeg, .jpg" />
<button type="submit">
Submit Form
</button>
</form>
Here is the main form with all the JS:
<script>
let visible = true
let sending = false
import { slide } from "svelte/transition"
let data = {
Name: undefined,
Location: undefined,
PrimaryURL: undefined,
SecondaryURL: undefined,
Biography: undefined,
TechSetup: undefined,
Email: undefined,
Phone: undefined
}
let form
let headShot
const encode = () => {
const formData = new FormData()
formData.append('form-name', 'info')
Object.keys(data).forEach((key)=>{
formData.append(key, data[key])
})
formData.append('Picture', [headShot.files[0]])
console.log([...formData])
return formData
}
const handleSubmit = event => {
sending = true // button formatting
// send the form data
fetch("/form/", {
method: "POST",
headers: { 'Content-Type': 'multipart/form-data' },
body: encode()
}).then(() => (visible = false)).catch(error => alert(error))
}
</script>
{#if visible}
<form
action="/form/"
on:submit|preventDefault={handleSubmit}
out:slide={{duration: 300}}
method="POST" data-netlify="true"
bind:this={form}
name="info"
enctype="multipart/form-data"
>
<label>
<header>Display Name</header>
<input type="text" required tabindex="0" name="Name" bind:value={data.Name} />
<footer>Example: Mary Gunn or Mary G.</footer>
</label>
<label>
<header>Location</header>
<input type="text" required tabindex="0" name="Location" bind:value={data.Location}/>
<footer>Example: Texas or Kansas City (can be general)</footer>
</label>
<label>
<header>Head Shot</header>
<input type="file" tabindex="0" name="Picture" accept=".png, .jpeg, .jpg" bind:this={headShot} />
<footer>Your favorite profile pic is great</footer>
</label>
<label>
<header>Primary Link URL</header>
<input type="text" required tabindex="0" name="PrimaryURL" bind:value={data.PrimaryURL} />
<footer>Your top link (youtube channel, blog, instagram etc)</footer>
</label>
<label>
<header>Secondary Link URL</header>
<input type="text" required tabindex="0" name="SecondaryURL" bind:value={data.SecondaryURL}/>
<footer>Your secondary link (youtube channel, blog, instagram etc)</footer>
</label>
<label>
<header>Short Bio</header>
<textarea required tabindex="0" name="Biography" maxlength="1000" bind:value={data.Biography} />
<footer>Used on our website. 1000 characters max.</footer>
</label>
<label>
<header>Tech Setup</header>
<textarea required tabindex="0" name="TechSetup" maxlength="500" bind:value={data.TechSetup} />
<footer>Breifly describe your tech setup for making videos. Do you use your phone? Web cam? Etc.</footer>
</label>
<h2>Private Contact Info</h2>
<p>We won't share this information with anyone. We like to have this information just-in-case.</p>
<label>
<header>Your Email</header>
<input type="email" required tabindex="0" name="Email" bind:value={data.Email} />
<footer>Best email for personal contact.</footer>
</label>
<label>
<header>Phone Number</header>
<input type="tel" required tabindex="0" name="Phone" bind:value={data.Phone} />
<footer>Best phone to reach you. (We sometimes text to remind about the show.)</footer>
</label>
<input type="hidden" name="form-name" value="info" />
<button type="submit">
{#if sending}
Sending...
{:else}
Submit Form
{/if}
</button>
</form>
{:else}
<p in:slide={{delay: 300, duration: 300}}>Thank you for sending in your info. We will reach out if we have any questions.</p>
{/if}
I have tried many many iterations of how I setup my formData and how I posted it. my encode() function builds and returns formData. My ‘Picture’ field is appended last, just like on the dummy form, and I have tried many different formats based on examples I have found here on the forum. None have worked.
Here is the encode function by itself:
const encode = () => {
const formData = new FormData()
formData.append('form-name', 'info')
Object.keys(data).forEach((key)=>{
formData.append(key, data[key])
})
formData.append('Picture', [headShot.files[0]])
console.log([...formData])
return formData
}
I have also tried encoding the post body as a string and just sending raw formData. Both have no problem posting the text fields to the admin. Neither post the file upload. For example, this works (sans the file upload)
body: new URLSearchParams(encode()).toString()
This also works the same way:
body: encode()
As for my ‘Picture’ form data, I have tried putting the file in an array like this (saw it as an example of a working ajax submit here on the forum)
formData.append('Picture', [headShot.files[0]])
and I have also tried with out the array bracket wrapper:
formData.append('Picture', headShot.files[0])
The file is in the formData when I log it. So I know the .append is working.
I feel like I’m not formatting it correctly. But I am in the dark with out any feedback from the Netlify form software.
If you look at how many times I’ve built my site in the past 48 hours you’ll understand that I might be a little frustrated.
If you want me to provide any other info / code / reasoning / anything please just ask. I would love to solve this and put it behind me.
I’ll even create an example repo for future SvelteKit users once we get it figured out.
Thanks.