Sortable icon indicating copy to clipboard operation
Sortable copied to clipboard

dataTransfer never passed to event objects in any event handler declared via options

Open swayok opened this issue 7 years ago • 8 comments

We have options.setData event handler where we can save some data to dataTransfer.

But in any other finishing event (onEnd, onUpdate, etc) we cannot access dataTransfer or at leas original event that has it.

new Sortable(el, {
    onEnd: function (event, otherArgMaybe) {
        console.log(event.originalEvent, event.dataTransfer, otherArgMaybe);
    }
});

This wll log undefined 3 times.

So how do we intend to access data stored in dataTransfer? Or at least original event... What was the purpose of setData option if you do not pass dataTransfer to other events?

swayok avatar Oct 19 '17 13:10 swayok

onEnd — is a custom event and in it never be accessible dataTransfer.

RubaXa avatar Oct 19 '17 15:10 RubaXa

Purpose of setData option only for preparing a native dnd.

RubaXa avatar Oct 19 '17 15:10 RubaXa

But if you console.log(evt) in _onDrop() you will be able to access dataTransfer and pass it to event object created by _dispatchEvent(). I haven't tested evt.dataTransfer.getData() though. Maybe it has no data at all. In this case maybe it will be useful to provide some api to store data on drag start and access it when item is dropped. This will make handling data more reliable in cases when content is generated from some objects outside of table row like it is done in DataTables. In my case after dropping a row DataTables api still has old indexes of rows but it may change in future.

swayok avatar Oct 19 '17 15:10 swayok

But if you console.log(evt) in _onDrop() you will be able to access dataTransfer

It's true only for a desktop, but not touch-devices. Therefore, if need your dataTransfer, add yours the drop listener on document.

RubaXa avatar Oct 19 '17 16:10 RubaXa

I understand the situation now. In this case dataTransfer is quite useless inside lib. Think about a possibility to pass data from drag-start to drag-end events triggered by lib. It should not be hard to implement along with oldIndex/newIndex but will allow more reliable data handling in drag-end events. Thanks for the lib! =)

swayok avatar Oct 20 '17 08:10 swayok

Any update on this item ? I am also looking for the possibility to pass data from the start event to the end event; e.g. pass custom data from the 'onClone' event which i can access at the 'onAdd' event. I need to pass some metadata when dropping into a different Sortable list. Thanks

paronne avatar Jun 15 '21 06:06 paronne

@paronne You can setData on the source list and getData from the onAdd event in the destination list, like this:

Source List:

setData: (dataTransfer, dragEl) => {
    dataTransfer.setData('Text', JSON.stringify({hello:'world'}));
}

Destination List:

onAdd: (evt) => {
    const data = JSON.parse(evt.originalEvent.dataTransfer.getData('Text'));
    console.log('onAdd data: ', data);
}

Note that you can only set 'text' data, but you can use JSON.stringify and parse to work around that and pass objects.

ataft avatar Sep 21 '21 23:09 ataft

@paronne You can setData on the source list and getData from the onAdd event in the destination list, like this:

Source List:

setData: (dataTransfer, dragEl) => {
    dataTransfer.setData('Text', JSON.stringify({hello:'world'}));
}

Destination List:

onAdd: (evt) => {
    const data = JSON.parse(evt.originalEvent.dataTransfer.getData('Text'));
    console.log('onAdd data: ', data);
}

Note that you can only set 'text' data, but you can use JSON.stringify and parse to work around that and pass objects.

This works, but when using Typescript the SortableEvent interface doesn't list originalEvent. Other than that it's working for me.

calebwaldner avatar Sep 30 '22 19:09 calebwaldner