Currently I am working on a scenario that I need to change the data attached to a dragging element after the dragging starts. Basically the drop zones are input fields or textareas so i would like to use the native event.dataTransfer.setData
since the native drag-drop can make the caret move with mouse.
Everything works perfectly at the beginning if i just call the setData()
synchronously in the listener of dragstart
event.
dragItem.addEventListener("dragstart",function(event){
event.dataTransfer.setData("text/plain","data set in dragstart");
})
However, my scenario could be that the data is from an asynchronouly callback function like an AJAX request. Then I attempted to call setData()
in this callback function but nothing seems to be successfully set.
dragItem.addEventListener("dragstart",function(event){
event.dataTransfer.setData("text/plain","data set in dragstart");
//like a callback in Ajax or resolve function of a promise.
setTimeout(function(){
console.log("attempt to set data asynchonrously after drag start");
event.dataTransfer.setData("text/plain","asynchonrously set data");
//looks like failed, the console output is empty, even not the original set one
console.log(event.dataTransfer.getData("text/plain"));
},200)
})
I also tried to change the data in dragenter
and even drop
event listeners of the drop zones. But there was still no luck.
This plunker shows what i have tried.
Then i referred to the MDN API document to find offical api description of the dataTransfer
object. But there is nothing about problems like asynchronously using setData
after drag start. One really weird thing is that if i try to compare the two dataTransfer
references in dragstart
and drop
event, the are NOT the same object. Now I have no clue what is actually happening.
So my questions are
dataTransfer
after the dragging is started with the native APIs (without using event.preventDefault
) ? event.preventDefault()
is used on drop
, it is not easy to get the caret move with mouse like the native dropping does.
Here is your answer. Firstly,You can only set data in your dragstart event. So, every time any dragstart event starts it sets value and what ever you set asynchronouly will not get reflected no matter what.
So, one thing that you can do is have a global object and set that on drag start event like this:
var someObj = {
asd : 'something'
}
and set in you dragstart callback, like this:
dragItem.addEventListener("dragstart",function(event){
event.dataTransfer.setData("text/plain", someObj.asd);
dataTransferObject = event.dataTransfer;
setTimeout(function(){
console.log("attempt to set data asynchonrously after drag start");
//event.dataTransfer.setData("text/plain","asynchonrously set data");
someObj.asd = 'asynchonrously';
//looks like failed, the console output is empty
console.log(event.dataTransfer.getData("text/plain"));
}, 100)
})
Object is by default reference type. Now, You can set someObj.asd to any value you want and you will see new value reflected. But there is a problem with this approach, value will be reflected after drop happens means after event has been ended.
So, to solve your problem what you can do is don't set any value on dragstart just set some value to someObj.asd on drag start and use someObj.asd on drop.
Here is a link of what i'm trying to explain: https://plnkr.co/edit/SZhI9lGRI37eEd1nWfhn?p=preview
see console on drop event you will see reflected value there.
DON'T SEE UI JUST GO FOR CONSOLE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With