I'm trying to implement a file dropper on a <div>
as a Svelte component. I've tried every combination of preventDefault
but the browser still loads the dropped file instead of passing it to the component.
<script>
function handleDrop(event) {
event.preventDefault();
console.log("onDrop");
}
function handleDragover(event) {
console.log("dragOver");
}
</script>
<style>
.dropzone {
display: block;
width: 100vw;
height: 300px;
background-color: #555;
}
</style>
<div class="dropzone" on:drop|preventDefault={handleDrop}
on:dragover|once|preventDefault={handleDragover}></div>
I've tried with and without event.preventDefault();
in handler functions. Also tried with on:dragenter
event and different combinations of modifiers, i.e. with stopPropagation
. The browser still opens the dropped file. What am I doing wrong? Thanks!
(UPDATE) FIX:
Okay, the culprit was the |once
modifier. Once removed from the on:dragover
in <div>
everything works great, except that dragover
event fires continuously while dragging across the div. event.preventDefault();
inside handler functions is not needed as the |preventDefault
modifier works correctly. Here is the code (omitting <style>
for brevity):
<script>
function handleDrop(event) {
console.log("onDrop");
}
function handleDragover(event) {
console.log("onDragOver");
}
</script>
<div class="dropzone" on:drop|preventDefault={handleDrop}
on:dragover|preventDefault={handleDragover}></div>
Not submitting this as an answer yet, because I would like to find out why I can't use |once
modifier for dragover
event, which would be useful for my app. Thanks!
I'm trying to implement a file dropper on a <div>
as a Svelte component. I've tried every combination of preventDefault
but the browser still loads the dropped file instead of passing it to the component.
<script>
function handleDrop(event) {
event.preventDefault();
console.log("onDrop");
}
function handleDragover(event) {
console.log("dragOver");
}
</script>
<style>
.dropzone {
display: block;
width: 100vw;
height: 300px;
background-color: #555;
}
</style>
<div class="dropzone" on:drop|preventDefault={handleDrop}
on:dragover|once|preventDefault={handleDragover}></div>
I've tried with and without event.preventDefault();
in handler functions. Also tried with on:dragenter
event and different combinations of modifiers, i.e. with stopPropagation
. The browser still opens the dropped file. What am I doing wrong? Thanks!
(UPDATE) FIX:
Okay, the culprit was the |once
modifier. Once removed from the on:dragover
in <div>
everything works great, except that dragover
event fires continuously while dragging across the div. event.preventDefault();
inside handler functions is not needed as the |preventDefault
modifier works correctly. Here is the code (omitting <style>
for brevity):
<script>
function handleDrop(event) {
console.log("onDrop");
}
function handleDragover(event) {
console.log("onDragOver");
}
</script>
<div class="dropzone" on:drop|preventDefault={handleDrop}
on:dragover|preventDefault={handleDragover}></div>
Not submitting this as an answer yet, because I would like to find out why I can't use |once
modifier for dragover
event, which would be useful for my app. Thanks!
2 Answers
Reset to default 18Problem:
This is a common gotcha rooted in HTML drag-and-drop (not Svelte's fault), where the last dragover
event must be canceled in order to cancel drop
. Looking at Svelte's once directive, it's just a closure that runs your handler one time. However, dragover will fire multiple times before being dropped, so the immediately preceding dragover is not prevented.
Solution:
Just include the directive without a handler:
<div
on:dragover|preventDefault
on:drop|preventDefault={handler}
>
<style>
.dropzone {
display: block;
width: 100vw;
height: 300px;
background-color: #555;
}
</style>
<div class="dropzone" on:drop={event => handleDrop(event)}
on:dragover={handleDragover}>
</div>
<script>
export function handleDragover (ev) {
ev.preventDefault();
console.log("dragOver");
}
export function handleDrop (ev) {
ev.preventDefault();
console.log("onDrop");
}
</script>
Look here: https://svelte.dev/repl/3721cbc9490a4c51b07068944a36a40d?version=3.4.2
https://v2.svelte.dev/repl?version=2.9.10&gist=8a9b145a738530b20d0c3ba138512289