I'm trying to integrate React DnD using the List
and ListItem
of Material UI and, while dragging, the entire list is shown as dragged element. I have tried to follow to the best of my understanding the examples, and here is what I have
import React, { Component, PropTypes } from 'react';
import { Random } from 'meteor/random';
import LocalizedComponent from '/client/components/LocalizedComponent';
// MUI
import { List, ListItem } from 'material-ui/List';
// ---
import { DragDropContext, DragSource, DropTarget } from 'react-dnd';
import { findDOMNode } from 'react-dom';
import HTML5Backend from 'react-dnd-html5-backend';
const itemSource = {
beginDrag(props) {
return {
id: props.id,
index: props.index
};
},
};
const itemTarget = {
hover(props, monitor, component) {
const dragIndex = monitor.getItem().index;
const hoverIndex = props.index;
// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return;
}
// Determine rectangle on screen
const hoverBoundingRect = findDOMNode(component).getBoundingClientRect();
// Get vertical middle
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
// Determine mouse position
const clientOffset = monitor.getClientOffset();
// Get pixels to the top
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%
// Dragging downwards
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return;
}
// Dragging upwards
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return;
}
// Time to actually perform the action
props.onMoveItem(dragIndex, hoverIndex);
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
monitor.getItem().index = hoverIndex;
},
};
class SortableListComponent extends Component {
render() {
const { children, onMoveItem } = this.props;
let index = 0;
return (
<List>
{ React.Children.map(children, child => React.cloneElement(child, {
id: Random.id(),
index: index++,
onMoveItem: onMoveItem
})) }
</List>
);
}
}
SortableListComponent.propTypes = {
onMoveItem: PropTypes.func.isRequired
};
class SortableListItemComponent extends Component {
render() {
const {
id,
index,
isDragging,
connectDragSource,
connectDropTarget,
onMoveItem,
...other
} = this.props;
const opacity = 1; // isDragging ? 0 : 1;
return connectDragSource(connectDropTarget(
<div style={{ opacity }}>
<ListItem { ...other } disabled={ isDragging } />
</div>
));
}
}
SortableListItemComponent.propTypes = {
connectDragSource: PropTypes.func.isRequired,
connectDropTarget: PropTypes.func.isRequired,
id: PropTypes.any.isRequired,
index: PropTypes.number.isRequired,
isDragging: PropTypes.bool.isRequired,
onMoveItem: PropTypes.func.isRequired,
};
export const SortableList = DragDropContext(HTML5Backend)(SortableListComponent);
export const SortableListItem = DropTarget('SortableListItem', itemTarget, connect => ({
connectDropTarget: connect.dropTarget(),
}))(DragSource('SortableListItem', itemSource, (connect, monitor) => ({
connectDragSource: connect.dragSource(),
isDragging: monitor.isDragging(),
}))(SortableListItemComponent));
Basically, I substitute List
for SortableList
and ListItem
for SortableListItem
, and this is what I see while dragging
What am I doing wrong?
Edit
For example, here is an example usage
<SortableList>
{ actions.map((action, index) => (
<SortableListItem id={ action.name } key={ index }
primaryText={ (index + 1) + '. ' + action.name }
onTouchTap={ this.handleActionEdit.bind(this, index) }
/>
)) }
</SortableList>
or
<SortableList>
{ actions.map((action, index) => (
<SortableListItem id={ action.name } key={ action.name }
primaryText={ (index + 1) + '. ' + action.name }
onTouchTap={ this.handleActionEdit.bind(this, index) }
/>
)) }
</SortableList>
etc.
It does not change a thing.