Maurio
Maurio

Reputation: 192

Changing CSS properties of an element while a file is being dragged

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

Answers (3)

csum
csum

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

Serg
Serg

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

Daniel Brambila
Daniel Brambila

Reputation: 21

Check out this solution, apparently you have to use X and Y coordinates:

https://stackoverflow.com/a/8615260/12448004

Upvotes: 1

Related Questions