2

I have a persistent drawer which holds a droppable list with draggable items. The functionality is there, but when dragging an item the item that is being dragged is not shown. I can drag the item perfectly and space is being allocated including animations as intended by the dnd framework, I just can't see what I am dragging. If I change the drawer to a permanent drawer, everything works as expected. Any suggestions?

My component (in prototype code): (The DragDropContext is declared in a parent component)

import React from 'react';
import { Divider, Drawer, IconButton, List, ListItem, Paper, 
withStyles } from 'material-ui';
import { Draggable, Droppable } from 'react-beautiful-dnd';

const styles = {
  list: {
    width: 250,
    marginTop: 70
  },
};

const getItemStyle = (isDragging, draggableStyle) => ({
  // some basic styles to make the items look a bit nicer
  userSelect: 'none',
  padding: 8 * 2,
  margin: `0 0 8px 0`,

  // change background colour if dragging
  background: isDragging ? 'lightgreen' : 'red',

  // styles we need to apply on draggables
      ...draggableStyle,

});

const getListStyle = isDraggingOver => ({
  background: isDraggingOver ? 'lightblue' : 'none',
  padding: 8,
  width: 250,
});

class WidgetDrawer extends React.Component {

  state = { items: [{ id: 1, content: 'Widget A'}, { id: 2, content: 'Widget B'}]};

  renderWidgets() {
    const widgets = [{
      name: 'Widget A'
    }, {
      name: 'Widget B'
    }];

    return widgets.map((widget, index) => {
      return <Draggable key={widget.name} draggableId={widget.name} index={index}>
                  {(provided, snapshot) => (
                    <div>
                      <div
                        ref={provided.innerRef}
                        {...provided.draggableProps}
                        {...provided.dragHandleProps}
                        style={getItemStyle(
                          snapshot.isDragging,
                          provided.draggableProps.style
                        )}
                      >
                        <ListItem>
                          <Paper>
                            {widget.name}
                          </Paper>
                        </ListItem>
                      </div>
                      {provided.placeholder}
                    </div>
                  )}
                </Draggable>
    })
  }

  render() {

    const { classes } = this.props;

    const fullList = (
      <div className={classes.list}>
          <Droppable droppableId="droppable">
          {(provided, snapshot) => (
            <div
              ref={provided.innerRef}
              style={getListStyle(snapshot.isDraggingOver)}
            >
              {this.state.items.map((item, index) => (
                <Draggable key={item.id} draggableId={item.id} index {index}>
                  {(provided, snapshot) => (
                    <div>
                      <div
                        ref={provided.innerRef}
                        {...provided.draggableProps}
                        {...provided.dragHandleProps}
                        style={getItemStyle(
                          snapshot.isDragging,
                          provided.draggableProps.style
                        )}
                      >
                        {item.content}
                      </div>
                      {provided.placeholder}
                    </div>
                  )}
                </Draggable>
              ))}
              {provided.placeholder}
            </div>
          )}
        </Droppable>
      </div>
    );

    return (
     <Drawer
       variant='permanent'
       anchor="right"
       open={this.props.open}
       onClose={this.props.toggleDrawer}>
      <div
        tabIndex={0}
        role="button"
        onClick={this.props.toggleDrawer}
        onKeyDown={this.props.toggleDrawer}
      >
        {fullList}
      </div>
    </Drawer>
    )
  }
}

export default withStyles(styles)(WidgetDrawer);
BennievanderWel
  • 63
  • 1
  • 1
  • 5
  • I actually noticed that that the component that is being dragged is shifted to the right for about a window width on pixels. If I start a drag and move my cursor all the way to the left hand of the screen, the dragged component shows. This probably has to do with the fact that the drawer in anchored at the right.. – BennievanderWel Apr 10 '18 at 11:19
  • for the future: https://github.com/mui-org/material-ui/pull/16281 My pr just got merged so this is a thing of the past :) – Gijs Boddeus Jun 19 '19 at 15:27

4 Answers4

6

This can be fixed by overriding the provided props in

const getItemStyle = (isDragging, draggableStyle) => ({
  ...draggableStyle,
  userSelect: 'none',
  position:static,
  padding: 8 * 2,
  margin: `0 0 8px 0`,
  background: isDragging ? 'lightgreen' : 'red',    
});
user9912639
  • 153
  • 6
6

For anyone else struggling with this. It is most likely because there is a transform set on your parent element. Even if it is a zero transform it will mess up transforms on the fixed child. So the only known solution is to remove the transform on the parent (or set it to 'none').

Or you can try messing with react portals for an alternative solution.

https://github.com/atlassian/react-beautiful-dnd/issues/128

FFF
  • 741
  • 1
  • 8
  • 19
2

I was having the same issue when using react-beautiful-dnd in the Material-UI drawer after "transform" the draggable item would disappear.

However, you can prevent this behavior by setting the transform property of the droppable list to none and preventing the inheritance of the transformation from the Drawer or any other transformed element.

<Droppable style={{ transform: "none" }} droppableId="droppable">
0

If any of the answers here don't work, I would suggest using their reparenting guide. Basically they've implemented a cloning api that will clone the dragged element to the root of dom. It supposedly more performant than using portals.