Table of contents
In the last blog post I built the functionality to handle form submission for the file upload itself, but we still didn't have a way to actually handle the files. In this post I'll set up the very basic markup as well as the accompanying script
functionality required.
Dependencies
The only extra dependency needed for this section, as mentioned in the last post, is Svelte File Dropzone, which can be installed by simply typing npm i -D svelte-file-dropzone
.
Script Setup
I'm going to use basic functionality for Dropzone, as indicated in the documentation with a couple of extra things:
- I will be adding a filter to not add files that include names already in the list of accepted files
- I will be wrapping the Dropzone in a
<form>
tag because that just feels more natural to me. - I will be adding functionality to remove one or all of the accepted files
The script
from the last blog post just had the files
object and the handleSubmit
method. Now I'll add a few more things.
// /src/routes/index.svelte
<script>
let files = {
accepted: [],
rejected: []
};
const accept = ['application/pdf'];
const maxSize = 2500000;
let loading = false;
const handleFilesSelect = (e) => {
const { acceptedFiles, fileRejections } = e.detail;
files.accepted = [
...files.accepted
.filter((file) => !acceptedFiles.map((f) => f.name).includes(file.name)),
...acceptedFiles
];
files.rejected = [...files.rejected, ...fileRejections];
};
const handleRemoveFile = (e, index) => {
files.accepted.splice(index, 1);
files.accepted = [...files.accepted];
};
const handleRemoveAll = () => {
files.accepted = [];
};
</script>
Markup
The markup for this is going to be wholly unspectacular in that I will not be including any styling whatsoever, but functionally this will work.
<main>
<form on:submit|preventDefault={handleSubmit}>
<Dropzone
{accept}
{maxSize}
on:drop={handleFilesSelect}
/>
{#if files.accepted.length > 0}
<div>
<h3>Files to be Uploaded</h3>
<ul>
{#each files.accepted as item, index}
<li>
{item.name}
<button type="button" on:click={(e) => handleRemoveFile(e, index)}>
x
</button>
</li>
{/each}
</ul>
</div>
<div>
<button type="submit" disabled={loading}>
{#if loading}
...Loading
{:else}
<span>Submit</span>
{/if}
</button>
<button type="button" disabled={loading} on:click={handleRemoveAll}>
Remove All
</button>
</div>
{/if}
</form>
</div>
Style
As an aside, I also added a little bit of styling to make it centered
<style>
main {
display: grid;
place-content: center;
height: 100vh;
}
</style>
The resulting page doesn't look great, but if you click on the box and choose the files you want to upload it should look like this Then if you click submit you'll see, once the process is completed, that the files show up in the assigned folder
Summary
That's it. The functionality is nothing terribly complicated when you look at everything in the aggregate, but all of the moving pieces can be a bit complex. Like I mentioned, I spent quite a bit of time trying to figure all of this out for the first time, but now that I've gotten it working I wanted to share it with you all. See you next time.