drag-drop-touch-js/dragdroptouch

Drag-Drop-Touch-Polyfill not working with React Grid Layout library

Closed this issue · 6 comments

Hello Sir,
I am trying to make the react grid layout library work in mobile resolution using drag-drop-touch-polyfill but it does not seem to work out. Getting the "Maximum update depth exceeded" error while dragging the element.

Have attached the code sandbox link below for reference:-
https://codesandbox.io/s/react-grid-layout-nested-grids-drag-from-outside-forked-rvg1ph?file=/DragDropTouch.js

I request you to please look into the issue. It will be great if you can help me out.

Thanks in advance!

Hello,

We are using RGL too on an internal project, and I faced the same issue.
I investigated a bit today, and it looks like at some point RGL is looking for an offset of the item being dragged.
Fun fact, the property read from the nativeEvent seems to be deprecated according the MDN page MouseEvent.layerX

Not totally confirmed on my side, but I tried a local copy of the polyfill and replaced the event binding with the related pointer events rather than the touch one.

// listen to touch events
if (navigator.maxTouchPoints) {
    var d = document,
        ts = this._touchstart.bind(this),
        tm = this._touchmove.bind(this),
        te = this._touchend.bind(this),
        opt = supportsPassive ? { passive: false, capture: false } : false;
-    d.addEventListener('touchstart', ts, opt);
-    d.addEventListener('touchmove', tm, opt);
-    d.addEventListener('touchend', te);
-    d.addEventListener('touchcancel', te);
+    d.addEventListener('pointerdown', ts, opt);
+    d.addEventListener('pointermove', tm, opt);
+    d.addEventListener('pointerup', te);
+    d.addEventListener('pointercancel', te);
}

Going with touch event seems to pass the information needed to compute offset, and React-Grid-Layout does not crash.

I can suggest a PR, but not sure about any side effects, I'm testing this change using a desktop + devtools touch emulation.

Thank you for the suggestion and for testing it.

I tested this change here but it didn't work for me (Surface touch screen, Chrome). ;-(

If you have any news on this issue, please feel free to share here.

For sure, I need to do more investigation, just after posting the suggestion, I noticed that some parts of the code looks for touches.
I may suggest a PR once I debugged it on my side.

BTW: great polyfill anyway, except the issue with React-Grid-Layout it works so great!

Glad you like it!

Hello, some feedbacks about the suggestion...

It looks like I was (very) tired and using touch events does not solve the issue, or if it is possible, it may involve many other changes to the current library.

But, I try another way, and for now it looks promising on the project I'm working on with React-Grid-Layout.

this._copyProps(evt, t, DragDropTouch._ptProps);
if (!evt.offsetX || !evt.offsetY || !evt.layerX || evt.layerY) { // block added to set "missing" properties for RGL
    var rect = target.getBoundingClientRect();
    evt.offsetX = evt.clientX;
    evt.offsetY = evt.clientY;
    evt.layerX = evt.pageX - rect.left;
    evt.layerY = evt.pageY - rect.top;
}
evt.dataTransfer = this._dataTransfer;

And I also had to add some CSS to avoid RGL placeholder to catch drag event and to produce some glitch

.react-grid-placeholder {
    pointer-events: none;
}

Current status can be consulted here:
https://codesandbox.io/s/react-grid-layout-nested-grids-drag-from-outside-forked-ibvst0?file=/DragDropTouch.js

I'm still facing issue about how to get correct values for layer[X|Y], using the target boundingClientRect looks pretty OK, but it is still wrong when the target has scrolled or the RGL contains a static element.

Pomax commented

I'm closing this mostly because of how much time has passed and how much the code has changed since this issue was filed. If this is still a concern, please file a new issue. I recently signed on to this project and would like to make sure we're covering all the bases, while also making sure there are no lingering issues based on old code.