Reputation: 192
I have set up a drag and drop box on my Vue JS web app. The element is a simple div which handles a file when it is dragged and dropped onto it.
I used https://www.raymondcamden.com/2019/08/08/drag-and-drop-file-upload-in-vuejs as a guideline.
HTML:
<div v-if="status == 'upload'">
<h3> Please fill the data sheet and upload it here!</h3>
<div class="downbox" @drop.prevent="addFile" @dragover.prevent>
<span style="font-size: 60px"><font-awesome-icon icon='cloud-upload-alt'/></span>
<br>
Click to Browse
<br>
or Drag and Drop a File Here
</div>
</div>
JS:
addFile: function(e){
let droppedFiles = e.dataTransfer.files;
if ((droppedFiles[0].name).slice(-5) !== '.xlsx') {
this.$swal({
text: "Please upload a file of type .xlsx",
title: "Incorrect File Type!",
icon: "error",
})
this.status = 'upload'
}
else {
this.file = droppedFiles
this.status = 'show'
}
},
removeFile: function(){
this.file = null
this.status = 'upload'
}
CSS:
.downbox {
width: 500px;
border-radius: 50px;
border-width: 6px;
border-color: white;
border-style: dashed;
background-color: #7a2ab3;
padding: 10px;
font-size: 25px;
font-weight: bold;
transition: 0.6s;
margin-left: auto;
margin-right: auto;
}
.downbox:hover{
background-color: #c56bc5;
}
As you can see, the background colour is changed when you mouse over the div.
However when I am dragging a file onto the div, this change of colour does not show up. So I don't know whether it does not count as a ":hover" if you are click dragging a file.
Either way I would like to know what I can add to the code in order to make the CSS background-color property change when I drag a file onto the div.
Upvotes: 5
Views: 9240
Reputation: 1992
You can listen for dragenter
and dragleave
events to handle this. But it can be tricky if you have other elements within your drop target element, because those will trigger dragleave
events on your drop target that you will want to ignore. But something like this should work:
<div :class="['downbox', drag_over ? 'over' : '']"
@dragenter="dragEnter"
@dragleave="dragLeave"
@dragover.prevent
@drop.prevent="addFile"
>
<div ref="others">
<span style="font-size: 60px"><font-awesome-icon icon='cloud-upload-alt'/></span>
<br>
Click to Browse
<br>
or Drag and Drop a File Here
</div>
</div>
In your event handlers, use over_others
to decide whether to set drag_over
to false
, which you don't want to do if you are still dragging over a child element. (see also, info on Vue $refs)
You may have more difficulty with your 60px span and the font-awesome-icon, but you should be able to extend the same principle to those elements if they give you trouble.
data() {
return {
drag_over: false, // dragging over the target OR any child element
over_others: false, // dragging over a child element
}
},
methods: {
dragEnter(e) {
if(e.target === this.$refs.others) this.over_others = true
else this.drag_over = true
},
dragLeave(e) {
if(e.target === this.$refs.others) this.over_others = false
else if(!this.over_others) this.drag_over = false
},
// ...
}
And add the css class:
.downbox:hover,
.downbox.over {
background-color: #c56bc5;
}
Upvotes: 3
Reputation: 845
I use the following solution (simplified here):
<template>
<div ref="drag" :class="{over: isOver}">
...
</div>
</template>
<script>
...
mounted () {
// add the needed event listeners to the container
this.$refs.drag.addEventListener("dragover", () => {
this.isOver = true; // add class on drag over
});
this.$refs.drag.addEventListener("dragleave", () => {
this.isOver= false; // remove class on drag leave
});
}
</script>
<css>
.over {...}
</css>
Upvotes: 6
Reputation: 21
Check out this solution, apparently you have to use X and Y coordinates:
https://stackoverflow.com/a/8615260/12448004
Upvotes: 1