nnyby
nnyby

Reputation: 4668

Capturing grid item click event in react-grid-layout

Is it possible to capture the grid item's click and cancel the drag event? I want to open a modal window when a grid item is clicked, but I can't figure out how to implement this. I'm capturing the click with onClick, but stopPropagation and preventDefault don't prevent the mousedown event that starts the dragging process.

Upvotes: 3

Views: 7261

Answers (4)

BringYouUp
BringYouUp

Reputation: 1

I solved this problem by creating key 'isDragging' in LocalStorage, because this solution synchronously executed and you can make delay.

Also you can use useForceUpdate custom hook in tandem with isDraggable useRef variable. I have a large nesting and this method did not help me.

Upvotes: 0

Nick Confrey
Nick Confrey

Reputation: 11

I was on a mobile browser, and so the react-grid-layout was eating the onClick event. Instead, I also listened for the onTouchStart listener, which worked.

<IconButton onTouchStart={() => onEditItem(id)} onClick={() => onEditItem(id)}>

Upvotes: 0

Damian Green
Damian Green

Reputation: 7505

I managed to get a workable solution by using movementx and movementy to see if there was actual real movement.

private onDrag = (
_layout: Layout[],
oldItem: Layout,
_newItem: Layout,
_placeholder: Layout,
e: MouseEvent,
_element: HTMLElement) => {
if (e.movementX !== 0 || e.movementY !== 0) {
  this.props.onWidgetDragStart(oldItem.i);
}  };

onWidgetDragStart fires an event that sets a variable (redux reducer:)

{
\[actionConstants.DASHBOARD.WIDGET_DRAGGING_STARTED\]: (
    state: DraftObject<DashboardsState>,
    action: Action<string>,
  ) => {
   state.isWidgetDragging = true;
   state.indexOfCurrentDraggedItem = action.payload;
 }
}

the click event then looks like this :

private onTitleClicked = (e: React.MouseEvent<HTMLDivElement>) => {
if (this.props.indexOfCurrentDraggedItem === this.props.options.id) {
  e.preventDefault();
  this.props.updatingIndexOfCurrentDraggedItem();
  return;
}

if (!this.props.isWidgetDragging && !this.state.editMode) {
  this.setState({
    editMode: true,
  });
}
{
\[actionConstants.DASHBOARD.WIDGET_DRAGGING_STARTED\]: (
state: DraftObject<DashboardsState>,
action: Action<string>,
) => {
  state.isWidgetDragging = true;
  state.indexOfCurrentDraggedItem = action.payload;
  },
};

where the updatingIndexOfCurrentDraggedItem action sets the indexOfCurrentDraggedItem to null and indexOfCurrentDraggedItem is injected as a prop to my widget component.

Upvotes: 0

Ricky Han
Ricky Han

Reputation: 1367

This can be done by passing a onMouseDown to a child div element.

<RGL ... >
  <div> // If you add onMouseDown here react-draggable will override it. You will have to use nested element to capture clicks
    <div onMouseDown={ e => e.stopPropagation() }>
      ...
    </div>
  <div>
</RGL>

Upvotes: 7

Related Questions