react-beautiful-dnd icon indicating copy to clipboard operation
react-beautiful-dnd copied to clipboard

transform on parent messes up dragging positioning

Open nickav opened this issue 8 years ago • 44 comments

Bug

Expected behaviour

Dragging an item maintains the proper positioning.

Actual behaviour

The item is pushed down by the height of the neighboring element.

Steps to reproduce

Create the following html structure:

<div>
    <div style="height: 100px;"></div>
    <div style="transform: translateY(0);">
        <!-- react-beautiful-dnd component -->
    </div>
</div>

Such that react beautiful dnd is monted as a sibling of an element with some height. The parent of the dnd component should have some transform property as well.

Browser version

Google Chrome: Version 61.0.3163.100 (Official Build) (64-bit)

Demo

https://www.webpackbin.com/bins/-KvOoCqQRkMYJzq63hlS

video: https://user-images.githubusercontent.com/5448363/166853462-519f2b79-43de-43b8-8912-6d84a71a1847.mov

https://user-images.githubusercontent.com/5448363/166853501-c2fb236c-61ce-4b7b-ad3c-24ab8fe51295.mov

nickav avatar Oct 01 '17 21:10 nickav

Check out the 'Warning: position: fixed' section under Draggable. At this stage having parent transforms are not supported. We might look at jumping to the new React portal solution to get around this in the future. However, for now it is not supported

alexreardon avatar Oct 01 '17 22:10 alexreardon

Thanks for raising this @nickaversano !!

alexreardon avatar Oct 01 '17 22:10 alexreardon

@alexreardon what about having an option to use pure position fixed positioning? In this mode, the position of the placeholder would be set entirely by top and left instead of using the transform property

nickav avatar Oct 01 '17 22:10 nickav

Interesting idea @nickaversano - worth thinking about. Generally updating top/left values during a drag is not ideal as it does not use the GPU. However, it may get around the issue. We are trying to keep the API as clean as possible so adding an option might not be ideal. In the mean time, you could achieve this yourself!

Here is the type for the draggable style:

export type DraggingStyle = {|
  // Allow scrolling of the element behind the dragging element
  pointerEvents: 'none',

  // `position: fixed` is used to ensure that the element is always positioned
  // in the correct position and ignores the surrounding position:relative parents
  position: 'fixed',

  // When we do `position: fixed` the element looses its normal dimensions,
  // especially if using flexbox. We set the width and height manually to
  // ensure the element has the same dimensions as before it started dragging
  width: number,
  height: number,

  // When we set the width and height they include the padding on the element.
  // We use box-sizing: border-box to ensure that the width and height are inclusive of the padding
  boxSizing: 'border-box',

  // We initially position the element in the same visual spot as when it started.
  // To do this we give the element the top / left position with the margins considered
  top: number,
  left: number,

  // We clear any top or left margins on the element to ensure it does not push
  // the element positioned with the top/left position.
  // We also clear the margin right / bottom. This has no positioning impact,
  // but it is cleanest to just remove all the margins rather than only the top and left.
  margin: 0,

  // Move the element in response to a user dragging
  transform: ?string,

  // When dragging or dropping we control the z-index to ensure that
  // the layering is correct
  zIndex: ZIndex,
|}

You could set the transform to null and update the top and left values yourself (remember to make the adjustments relative to the initial top and left values).

Here is the format of the transform value:

transform: `translate(${point.x}px, ${point.y}px)`

alexreardon avatar Oct 01 '17 22:10 alexreardon

Let me know how you go

alexreardon avatar Oct 02 '17 00:10 alexreardon

I think for now I'm just going to remove the transform on the parent. I'm doing an animation, but can remove it after the animation completes.

nickav avatar Oct 02 '17 01:10 nickav

Even better!

alexreardon avatar Oct 02 '17 01:10 alexreardon

I managed to get this to work with Portal from react-dom without changing styles etc.

I added a dom element into my html

<div id="draggable"></div>

Added the following styles

position: absolute;
pointer-events: none;
height: 100%;
width: 100%;

And then added this to the Draggable

import React, { PureComponent } from 'react';
import { createPortal } from 'react-dom';

const _dragEl = document.getElementById('draggable');

class DraggableGoal extends PureComponent {
  optionalPortal(styles, element) {
    if(styles.position === 'fixed') {
      return createPortal(
        element,
        _dragEl,
      );
    }
    return element;
  }
  render() {
    const { item } = this.props;
    return (
      <Draggable>
        {(provided, snapshot) => {
          return (
            <div>
              {this.optionalPortal(provided.draggableStyle, (
                <div
                  ref={provided.innerRef}
                  style={provided.draggableStyle}
                  {...provided.dragHandleProps}
                >
                  {item}
                </div>
              ))}
              {provided.placeholder}
            </div>
          );
        }}
      </Draggable>
    );
  }
}

Hope this helps :)

kasperpihl avatar Nov 27 '17 15:11 kasperpihl

Sorry if i'm not supposed to post in closed issues, but i figured this might help if someone else is still having the same problem.

I had the same issue when moving an item from a nested list to the parent list, due to the nested lists' container getting transformed when it is "moved down" to show where the dragged item will drop. The problem itself is that when an item (in this case the nested list) gets transformed, that element becomes the new target container for any child elements with position: fixed (essentially changing it to position: absolute), so the nested item i am trying to drag does not position itself to the viewport, but rather to it's parent container.

I finally managed to make a CSS based workaround and thought I should share it incase someone else still has the same problem.

My solution was to monitor the parent containers styles and when it gets a transform, i recalculate the inner items transform to compensate with the formula current X - parentX - position.left and currentY - parentY - position.top where currentX and currentY is the transform properties i get from provided.draggableProps.style.transform there is also a +20in there to account for some margins in my case.

<Draggable
         key={index}
         draggableId={cel.contentId}
         index={index}>
                {(provided, snapshot) => {
                           let transform = provided.draggableProps.style.transform;
                           if(snapshot.isDragging){
                           let regex = new RegExp('translate\\((.*?)px, (.*?)px\\)');

                           //the transform property of parent style gotten through reference and passed in as a prop
                           let parentValues = regex.exec(this.props.parentTransform ||"")
                           let childValues = regex.exec(provided.draggableProps.style.transform || "");

                           //if both the parent (the nested list) and the child (item beeing dragged) has transform values, recalculate the child items transform to account for position fixed not working
                           if(childValues != null && parentValues != null){
                                   let x = (parseFloat(childValues[1], 10)) - ((parseFloat(parentValues[1], 10)) + (parseFloat(provided.draggableProps.style.left,10))) + 20;
                                   let y = (parseFloat(childValues[2], 10)) - ((parseFloat(parentValues[2], 10)) + (parseFloat(provided.draggableProps.style.top, 10)));
                                   transform = `translate(${x}px, ${y}px)`;
                          }
              } 
return (<div
        {...provided.draggableProps}
        {...this.props}
        ref={provided.innerRef}
        isDragging={snapshot.isDragging}
        style={{...provided.draggableProps.style, transform}}
        >(... _inner content removed for brevity_ )</div>)
}
</Draggable>

Valoran avatar Sep 02 '19 09:09 Valoran

Sorry if i'm not supposed to post in closed issues, but i figured this might help if someone else is still having the same problem.

I had the same issue when moving an item from a nested list to the parent list, due to the nested lists' container getting transformed when it is "moved down" to show where the dragged item will drop. The problem itself is that when an item (in this case the nested list) gets transformed, that element becomes the new target container for any child elements with position: fixed (essentially changing it to position: absolute), so the nested item i am trying to drag does not position itself to the viewport, but rather to it's parent container.

I finally managed to make a CSS based workaround and thought I should share it incase someone else still has the same problem.

My solution was to monitor the parent containers styles and when it gets a transform, i recalculate the inner items transform to compensate with the formula current X - parentX - position.left and currentY - parentY - position.top where currentX and currentY is the transform properties i get from provided.draggableProps.style.transform there is also a +20in there to account for some margins in my case.

<Draggable
         key={index}
         draggableId={cel.contentId}
         index={index}>
                {(provided, snapshot) => {
                           let transform = provided.draggableProps.style.transform;
                           if(snapshot.isDragging){
                           let regex = new RegExp('translate\\((.*?)px, (.*?)px\\)');

                           //the transform property of parent style gotten through reference and passed in as a prop
                           let parentValues = regex.exec(this.props.parentTransform ||"")
                           let childValues = regex.exec(provided.draggableProps.style.transform || "");

                           //if both the parent (the nested list) and the child (item beeing dragged) has transform values, recalculate the child items transform to account for position fixed not working
                           if(childValues != null && parentValues != null){
                                   let x = (parseFloat(childValues[1], 10)) - ((parseFloat(parentValues[1], 10)) + (parseFloat(provided.draggableProps.style.left,10))) + 20;
                                   let y = (parseFloat(childValues[2], 10)) - ((parseFloat(parentValues[2], 10)) + (parseFloat(provided.draggableProps.style.top, 10)));
                                   transform = `translate(${x}px, ${y}px)`;
                          }
              } 
return (<div
        {...provided.draggableProps}
        {...this.props}
        ref={provided.innerRef}
        isDragging={snapshot.isDragging}
        style={{...provided.draggableProps.style, transform}}
        >(... _inner content removed for brevity_ )</div>)
}
</Draggable>

there isn't an official solution for now, right ?

lkiarest avatar Oct 21 '19 07:10 lkiarest

I managed to get this to work with Portal from react-dom without changing styles etc.

I added a dom element into my html

<div id="draggable"></div>

Added the following styles

position: absolute;
pointer-events: none;
height: 100%;
width: 100%;

And then added this to the Draggable

import React, { PureComponent } from 'react';
import { createPortal } from 'react-dom';

const _dragEl = document.getElementById('draggable');

class DraggableGoal extends PureComponent {
  optionalPortal(styles, element) {
    if(styles.position === 'fixed') {
      return createPortal(
        element,
        _dragEl,
      );
    }
    return element;
  }
  render() {
    const { item } = this.props;
    return (
      <Draggable>
        {(provided, snapshot) => {
          return (
            <div>
              {this.optionalPortal(provided.draggableStyle, (
                <div
                  ref={provided.innerRef}
                  style={provided.draggableStyle}
                  {...provided.dragHandleProps}
                >
                  {item}
                </div>
              ))}
              {provided.placeholder}
            </div>
          );
        }}
      </Draggable>
    );
  }
}

Hope this helps :)

Budy you saved my life many thankful to you

kaanbayram avatar Dec 24 '19 07:12 kaanbayram

This mostly worked for me.. Or, at least, now when I do the drag things align. However when I drop the animation zooms back to the position it would have been in without the transform.

Is there a way that I can adjust the drop animation start position?

zachsa avatar Jan 29 '20 14:01 zachsa

This mostly worked for me.. Or, at least, now when I do the drag things align. However when I drop the animation zooms back to the position it would have been in without the transform.

Is there a way that I can adjust the drop animation start position?

@zachsa

if you just want to change position:fixed property you don't have to use portal. You can do override. If you don't know how you can do i can look my old project for you. Portal will isolate parent css from child DOM element.

kaanbayram avatar Jan 29 '20 14:01 kaanbayram

Ah. I didn't think of adjusting the position in the style element. Thank you

zachsa avatar Jan 29 '20 15:01 zachsa

Sorry if i'm not supposed to post in closed issues, but i figured this might help if someone else is still having the same problem. I had the same issue when moving an item from a nested list to the parent list, due to the nested lists' container getting transformed when it is "moved down" to show where the dragged item will drop. The problem itself is that when an item (in this case the nested list) gets transformed, that element becomes the new target container for any child elements with position: fixed (essentially changing it to position: absolute), so the nested item i am trying to drag does not position itself to the viewport, but rather to it's parent container. I finally managed to make a CSS based workaround and thought I should share it incase someone else still has the same problem. My solution was to monitor the parent containers styles and when it gets a transform, i recalculate the inner items transform to compensate with the formula current X - parentX - position.left and currentY - parentY - position.top where currentX and currentY is the transform properties i get from provided.draggableProps.style.transform there is also a +20in there to account for some margins in my case.

<Draggable
         key={index}
         draggableId={cel.contentId}
         index={index}>
                {(provided, snapshot) => {
                           let transform = provided.draggableProps.style.transform;
                           if(snapshot.isDragging){
                           let regex = new RegExp('translate\\((.*?)px, (.*?)px\\)');

                           //the transform property of parent style gotten through reference and passed in as a prop
                           let parentValues = regex.exec(this.props.parentTransform ||"")
                           let childValues = regex.exec(provided.draggableProps.style.transform || "");

                           //if both the parent (the nested list) and the child (item beeing dragged) has transform values, recalculate the child items transform to account for position fixed not working
                           if(childValues != null && parentValues != null){
                                   let x = (parseFloat(childValues[1], 10)) - ((parseFloat(parentValues[1], 10)) + (parseFloat(provided.draggableProps.style.left,10))) + 20;
                                   let y = (parseFloat(childValues[2], 10)) - ((parseFloat(parentValues[2], 10)) + (parseFloat(provided.draggableProps.style.top, 10)));
                                   transform = `translate(${x}px, ${y}px)`;
                          }
              } 
return (<div
        {...provided.draggableProps}
        {...this.props}
        ref={provided.innerRef}
        isDragging={snapshot.isDragging}
        style={{...provided.draggableProps.style, transform}}
        >(... _inner content removed for brevity_ )</div>)
}
</Draggable>

there isn't an official solution for now, right ?

I found that although this fixed the dragging offset, when I drop the item the animation is from where the original position would have been

zachsa avatar Jan 29 '20 15:01 zachsa

@zachsa i think you are changing your Droppable area's location after render. Because of position:fixed even if you change this property for draggable element acting as it was in its old position. Because Droppable area's position property still position:fixed. And unfortunately you can't override droppable area's css as draggable element. Sorry for my english. I was have similar problem as like yours. https://github.com/kaanbayram/React-antdesign-menu-beatiful-dnd

This is my project, i think this can be helpful to you.

kaanbayram avatar Jan 30 '20 06:01 kaanbayram

thank you - that does look like it's exactly what i want to do. Before I start looking through the source (still quite difficult for me), would you mind if I just double check with you that I'm on the right track?

  • I have a div that can be dragged around the screen (such as in your code)
  • This div contains a simple DND list.
  • The drag is enabled by traslate instead of changing absolute positioning. Therefore DND drag is incorrect
  • I was able to correct the draggable elements traslate offset. But not the drop animation. The result is that when I 'dropped' the element it would fly back to where it would naturally be and then animate from there

It looks like this is something that your code will fix! I'll give it a go - please let me know if I'm NOT on the correct track !!

zachsa avatar Jan 30 '20 07:01 zachsa

Firstly sorry for my complicated code. I think yes you are in correct track. If you wish you can share your project, maybe i can help to you better.

kaanbayram avatar Jan 30 '20 14:01 kaanbayram

I've reopening this as there is still discussion going. I will try to get to it soon

alexreardon avatar Jan 30 '20 22:01 alexreardon

Thank you - @kaanbayram. no need to apologize for showing me helpful code! For whatever reason though, the project when installed and started showed the same problem that I was having.

I don't know why this would be the case, since I see from comments above that you looked at the same portal code that I used, and which worked - something along the lines of this:

import React, { PureComponent } from 'react';
import { createPortal } from 'react-dom';

const _dragEl = document.getElementById('draggable');

class DraggableGoal extends PureComponent {
  optionalPortal(styles, element) {
    if(styles.position === 'fixed') {
      return createPortal(
        element,
        _dragEl,
      );
    }
    return element;
  }
  render() {
    const { item } = this.props;
    return (
      <Draggable>
        {(provided, snapshot) => {
          return (
            <div>
              {this.optionalPortal(provided.draggableStyle, (
                <div
                  ref={provided.innerRef}
                  style={provided.draggableStyle}
                  {...provided.dragHandleProps}
                >
                  {item}
                </div>
              ))}
              {provided.placeholder}
            </div>
          );
        }}
      </Draggable>
    );
  }
}

However the styling didn't quite work out the box. @alexreardon. What are the challenges of allowing us to pass a ref to a parent that gets the transform style, and then 'normalizing' the transforms on the draggable elements when dragging and dropping (sorry, I don't know the library well enough to know if this makes sense). If it did this... then from the user perspective it would 'just work'. (Although I am happy to learn about React portals - something I had no prior knowledge of).

zachsa avatar Jan 31 '20 07:01 zachsa

I managed to get this to work with Portal from react-dom without changing styles etc.

I added a dom element into my html

<div id="draggable"></div>

Added the following styles

position: absolute;
pointer-events: none;
height: 100%;
width: 100%;

And then added this to the Draggable

import React, { PureComponent } from 'react';
import { createPortal } from 'react-dom';

const _dragEl = document.getElementById('draggable');

class DraggableGoal extends PureComponent {
  optionalPortal(styles, element) {
    if(styles.position === 'fixed') {
      return createPortal(
        element,
        _dragEl,
      );
    }
    return element;
  }
  render() {
    const { item } = this.props;
    return (
      <Draggable>
        {(provided, snapshot) => {
          return (
            <div>
              {this.optionalPortal(provided.draggableStyle, (
                <div
                  ref={provided.innerRef}
                  style={provided.draggableStyle}
                  {...provided.dragHandleProps}
                >
                  {item}
                </div>
              ))}
              {provided.placeholder}
            </div>
          );
        }}
      </Draggable>
    );
  }
}

Hope this helps :)

This almost works form me, it fixes dragging positioning issue but all the other cards disappears, I just need to tweak this a little more.

cuxs avatar Mar 28 '20 23:03 cuxs

Sorry if i'm not supposed to post in closed issues, but i figured this might help if someone else is still having the same problem.

I had the same issue when moving an item from a nested list to the parent list, due to the nested lists' container getting transformed when it is "moved down" to show where the dragged item will drop. The problem itself is that when an item (in this case the nested list) gets transformed, that element becomes the new target container for any child elements with position: fixed (essentially changing it to position: absolute), so the nested item i am trying to drag does not position itself to the viewport, but rather to it's parent container.

I finally managed to make a CSS based workaround and thought I should share it incase someone else still has the same problem.

My solution was to monitor the parent containers styles and when it gets a transform, i recalculate the inner items transform to compensate with the formula current X - parentX - position.left and currentY - parentY - position.top where currentX and currentY is the transform properties i get from provided.draggableProps.style.transform there is also a +20in there to account for some margins in my case.

<Draggable
         key={index}
         draggableId={cel.contentId}
         index={index}>
                {(provided, snapshot) => {
                           let transform = provided.draggableProps.style.transform;
                           if(snapshot.isDragging){
                           let regex = new RegExp('translate\\((.*?)px, (.*?)px\\)');

                           //the transform property of parent style gotten through reference and passed in as a prop
                           let parentValues = regex.exec(this.props.parentTransform ||"")
                           let childValues = regex.exec(provided.draggableProps.style.transform || "");

                           //if both the parent (the nested list) and the child (item beeing dragged) has transform values, recalculate the child items transform to account for position fixed not working
                           if(childValues != null && parentValues != null){
                                   let x = (parseFloat(childValues[1], 10)) - ((parseFloat(parentValues[1], 10)) + (parseFloat(provided.draggableProps.style.left,10))) + 20;
                                   let y = (parseFloat(childValues[2], 10)) - ((parseFloat(parentValues[2], 10)) + (parseFloat(provided.draggableProps.style.top, 10)));
                                   transform = `translate(${x}px, ${y}px)`;
                          }
              } 
return (<div
        {...provided.draggableProps}
        {...this.props}
        ref={provided.innerRef}
        isDragging={snapshot.isDragging}
        style={{...provided.draggableProps.style, transform}}
        >(... _inner content removed for brevity_ )</div>)
}
</Draggable>

Worked for me but I have changed this piece to work fine:

const x =
  parseFloat(childValues[1], 10) -
  parseFloat(
    provided.draggableProps.style.left,
    10,
  )
const y =
  parseFloat(childValues[2], 10) -
  parseFloat(
    provided.draggableProps.style.top,
    10,
  )

And this one too:

style={{
  ...provided.draggableProps.style,
  transform,
  position: snapshot.isDragging
    ? 'absolute'
    : '',
}}

hemavidal avatar Apr 08 '20 19:04 hemavidal

@kasperpihl where I can buy beer for you? You saved my day.

nikitowsky avatar Jul 14 '20 13:07 nikitowsky

That is super exhilarating to hear @borisowsky, @kasperpihl, I tried implementing a solution in codesandbox here: https://codesandbox.io/s/react-beautiful-dnd-h4lk7?file=/src/index.js

In this example, I translate the drag and drop list by 30 in the x and y direction, however, even after using portals, the dragging behavior is offset. Any help/ a working example on code sandbox would be amazing, thank you!

AnujVarma avatar Jul 17 '20 17:07 AnujVarma

Sorry if i'm not supposed to post in closed issues, but i figured this might help if someone else is still having the same problem.

I had the same issue when moving an item from a nested list to the parent list, due to the nested lists' container getting transformed when it is "moved down" to show where the dragged item will drop. The problem itself is that when an item (in this case the nested list) gets transformed, that element becomes the new target container for any child elements with position: fixed (essentially changing it to position: absolute), so the nested item i am trying to drag does not position itself to the viewport, but rather to it's parent container.

I finally managed to make a CSS based workaround and thought I should share it incase someone else still has the same problem.

My solution was to monitor the parent containers styles and when it gets a transform, i recalculate the inner items transform to compensate with the formula current X - parentX - position.left and currentY - parentY - position.top where currentX and currentY is the transform properties i get from provided.draggableProps.style.transform there is also a +20in there to account for some margins in my case.

<Draggable
         key={index}
         draggableId={cel.contentId}
         index={index}>
                {(provided, snapshot) => {
                           let transform = provided.draggableProps.style.transform;
                           if(snapshot.isDragging){
                           let regex = new RegExp('translate\\((.*?)px, (.*?)px\\)');

                           //the transform property of parent style gotten through reference and passed in as a prop
                           let parentValues = regex.exec(this.props.parentTransform ||"")
                           let childValues = regex.exec(provided.draggableProps.style.transform || "");

                           //if both the parent (the nested list) and the child (item beeing dragged) has transform values, recalculate the child items transform to account for position fixed not working
                           if(childValues != null && parentValues != null){
                                   let x = (parseFloat(childValues[1], 10)) - ((parseFloat(parentValues[1], 10)) + (parseFloat(provided.draggableProps.style.left,10))) + 20;
                                   let y = (parseFloat(childValues[2], 10)) - ((parseFloat(parentValues[2], 10)) + (parseFloat(provided.draggableProps.style.top, 10)));
                                   transform = `translate(${x}px, ${y}px)`;
                          }
              } 
return (<div
        {...provided.draggableProps}
        {...this.props}
        ref={provided.innerRef}
        isDragging={snapshot.isDragging}
        style={{...provided.draggableProps.style, transform}}
        >(... _inner content removed for brevity_ )</div>)
}
</Draggable>

Thank you for your share. I have a question here how can I get/set parentTransform in props?

ShongSu avatar Jul 30 '20 17:07 ShongSu

I had the same issue. Following the great solution of @kasperpihl, I created a simple hook do do the trick:

Hook:

const useDraggableInPortal = () => {
    const self = useRef({}).current;

    useEffect(() => {
        const div = document.createElement('div');
        div.style.position = 'absolute';
        div.style.pointerEvents = 'none';
        div.style.top = '0';
        div.style.width = '100%';
        div.style.height = '100%';
        self.elt = div;
        document.body.appendChild(div);
        return () => {
            document.body.removeChild(div);
        };
    }, [self]);

    return (render) => (provided, ...args) => {
        const element = render(provided, ...args);
        if (provided.draggableProps.style.position === 'fixed') {
            return createPortal(element, self.elt);
        }
        return element;
    };
};

Usage:

Considering the following component:

const MyComponent = (props) => {
  return (
    <DragDropContext onDragEnd={/* ... */}>
      <Droppable droppableId="droppable">
        {({ innerRef, droppableProps, placeholder }) => (
          <div ref={innerRef} {...droppableProps}>
            {props.items.map((item, index) => (
              <Draggable key={item.id} draggableId={item.id} index={index}>
                {(provided) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                  >
                    {item.title}
                  </div>
                )}
              </Draggable>
            )}
            {placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
};

Just call the hook and use the returned function to wrap the children callback of <Draggable /> component:

const MyComponent = (props) => {
+ const renderDraggable = useDraggableInPortal();

  return (
    <DragDropContext onDragEnd={/* ... */}>
      <Droppable droppableId="droppable">
        {({ innerRef, droppableProps, placeholder }) => (
          <div ref={innerRef} {...droppableProps}>
            {props.items.map((item, index) => (
              <Draggable key={item.id} draggableId={item.id} index={index}>
+               {renderDraggable((provided) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                  >
                    {item.title}
                  </div>
                ))}
              </Draggable>
+           ))}
            {placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
};

Hope it'll help.

renaudtertrais avatar Aug 05 '20 09:08 renaudtertrais

I managed to get this to work with Portal from react-dom without changing styles etc.

I added a dom element into my html

<div id="draggable"></div>

Added the following styles

position: absolute;
pointer-events: none;
height: 100%;
width: 100%;

And then added this to the Draggable

import React, { PureComponent } from 'react';
import { createPortal } from 'react-dom';

const _dragEl = document.getElementById('draggable');

class DraggableGoal extends PureComponent {
  optionalPortal(styles, element) {
    if(styles.position === 'fixed') {
      return createPortal(
        element,
        _dragEl,
      );
    }
    return element;
  } #
  render() {
    const { item } = this.props;
    return (
      <Draggable>
        {(provided, snapshot) => {
          return (
            <div>

> {optionalPortal(provided.draggableProps.style, (

            <div
              ref={provided.innerRef}
              style={provided.draggableStyle}
              {...provided.dragHandleProps}
            >
              {item}
            </div>
          ))}
          {provided.placeholder}
        </div>
      );
    }}
  </Draggable>
);

} }


Hope this helps :)

This works great, but just use: {optionalPortal(provided.draggableProps.style, (

ghost avatar Sep 01 '20 16:09 ghost

I face the same out-of-position problem.

When I try to implement it like @daljeetv I get an error Unable to find draggable element with id: X when clicking the item that I would like to move.

Do you guys have any ideas what the reason could be?

Maxeeezy avatar Oct 29 '20 17:10 Maxeeezy

Anyone who has still this problem I made a repository where I made an example for it and in the README you can also find a more simple solution. I found it from here in a comment and it works fine.

Note: I had another problem where the dragged div was disappear and I found out it was because of z-index and it dropped behind the parent div. So if e.g. you have a sidebar and its z-index is 999 you have to set the div of Draggable component above that (e.g. z-index: 1000;).

Here is my repo: https://github.com/DucktorDanny/react-beautiful-dnd-example

I hope I could help. :)

ducktordanny avatar Jan 31 '21 18:01 ducktordanny

Hey Danny, thank you so much!

Holen Sie sich Outlook für Androidhttps://aka.ms/ghei36


From: ducktor [email protected] Sent: Sunday, January 31, 2021 7:35:36 PM To: atlassian/react-beautiful-dnd [email protected] Cc: Maxeeezy [email protected]; Comment [email protected] Subject: Re: [atlassian/react-beautiful-dnd] transform on parent messes up dragging positioning (#128)

Anyone who has still this problem I made a repository where I made an example for it and in the README you can also find a more simple solution. I found it from here in a comment and it works fine.

Note: I had another problem where the dragged div was disappear and I found out it was because of z-index and it dropped behind the parent div. So if e.g. you have a sidebar and its z-index is 999 you have to set the div of Draggable component above that (e.g. z-index: 1000;).

Here is my repo: https://github.com/DucktorDanny/react-beautiful-dnd-example

I hope I could help. :)

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/atlassian/react-beautiful-dnd/issues/128#issuecomment-770428164, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AKDBV6LFZ4KCZCQFD2NMZ73S4WPHRANCNFSM4D5IE6IA.

Maxeeezy avatar Feb 01 '21 10:02 Maxeeezy