I'm using svelte
and svelte-forms-lib
. I've got a form component that looks like:
<script> import { createForm } from "svelte-forms-lib"; export let mode; export let submitFn; export let formData = {}; let fileInput = ""; let imagePreview = ""; const handleDrop = (e) => { e.preventDefault(); e.stopPropagation(); const file = e.dataTransfer.files[0]; handleImage(file) } const handleImage = imageFile => { if (imageFile) { const fileURL = URL.createObjectURL(imageFile) const reader = new FileReader(); reader.onload = readerEvent => { formData.image = readerEvent.target.result; } imagePreview = fileURL; } } const clearImagePreview = () => { imagePreview = ""; formData.image = ""; } const { form, handleChange, handleSubmit } = createForm({ initialValues: formData, onSubmit: async data => { console.log("submitting form") console.log(data) } })</script><form on:submit|preventDefault={handleSubmit} enctype="multipart/form-data">{#if imagePreview === ""}<label for="dropzone-file" class="flex flex-col justify-center items-center w-full h-64 bg-gray-50 rounded-lg border-2 border-gray-300 border-dashed cursor-pointer dark:hover:bg-bray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600"><div class="flex flex-col justify-center items-center pt-5 pb-6" on:drop={handleDrop} ondragover="return false"><svg aria-hidden="true" class="mb-3 w-10 h-10 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"></path></svg><p class="mb-2 text-sm text-gray-500 dark:text-gray-400"><span class="font-semibold">Click to upload</span> or drag and drop</p><p class="text-xs text-gray-500 dark:text-gray-400">SVG, PNG, JPG or GIF (MAX. 800x400px)</p></div><input id="dropzone-file" bind:files={formData.image} name="image" on:change={ e => handleImage(e.target.files[0])} type="file" class="hidden" /></label> {:else}<img src={imagePreview} class="flex flex-col justify-center items-center w-full h-64 bg-gray-50 rounded-lg border-2 border-gray-300 border-dashed dark:hover:bg-bray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600" /><a href="#" on:click={clearImagePreview}>Remove</a> {/if}<div class="grid grid-cols-1"><div class="p-4 flex item-center justify-center"><button type="submit" class="btn btn-active btn-primary"> { mode == "new" ? "Save" : "Update" }</button></div></div></form>
When I click the Save
button, I don't see the data for my image in the object. Basically I've identified 2 issues:
reader.onload
doesn't seem to be fired. If I add logs withinreader.onload
they never appear on the console.If I run a method from the
reader
, let's sayreader.readAsDataURL(imageFile)
:
const handleImage = imageFile => { if (imageFile) { const fileURL = URL.createObjectURL(imageFile) const reader = new FileReader(); const dataAsURL = reader.readAsDataURL(imageFile); reader.onload = readerEvent => { console.log("here in reader.onload") formData.image = readerEvent.target.result; console.log("reader event..."); console.log(formData.image); } imagePreview = fileURL; }
I do see the logs from reader.onload
. Furthermore, I can see that formData.image
is being populated with the base64 representation of the image BUT when I click the submit button the formData
object does not have the image
property.
For simplicity I've omitted all other fields in the form, most of them of type text, but they do appear when the form is submitted. For instance:
<input id="barcode" bind:value={formData.barcode} on:change={handleChange} type="text" class="input w-full py-4 font-medium bg-gray-100 border-gray-200 text-sm focus:outline-none focus:border-gray-400 focus:bg-white" />
is being submitted.
What's going on here?