3

I am setting up a nested drag and drop with React-DnD. The below image gives you a better idea of my approach. 1

All the elements are Draggable and Droppable. Example - Field one, two, Group 1, Field one Group one, and Sub Group 1 all can be draggable and droppable.

Did:

  1. I can sort the parent items Field one, Field two, Group 1 - drag and drop, sortable

Need help on this:

  1. Need to sort all the fields that are inside the group and outside the group.
  2. Any item can be grouped and ungrouped.

Example:

scenario 1: User will drag the Field one group one item and drop it below Field two.

scenario 2: User will drag the Field two item and drop it inside the Group 1/Sub group 1.

Whenever I drag an item that is tracked by using the below line: while hovering on the particular item ref.current will give the particular item.

import { useRef } from "react";
import { useDrag, useDrop } from "react-dnd";
import { ItemTypes } from "./ItemTypes";
const style = {
  border: "1px dashed gray",
  padding: "0.5rem 1rem",
  marginBottom: ".5rem",
  backgroundColor: "white",
  cursor: "move"
};
export const Card = ({ id, text, index, moveCard, children, type }) => {
  const ref = useRef(null);
  const [{ handlerId }, drop] = useDrop({
    accept: ItemTypes.CARD,
    collect(monitor) {
      return {
        handlerId: monitor.getHandlerId()
      };
    },
    hover(item, monitor) {
      if (!ref.current) {
        return;
      }
      const dragIndex = item.index;
      const hoverIndex = index;
      // Don't replace items with themselves
      if (dragIndex === hoverIndex) {
        return;
      }
      // Determine rectangle on screen
      const hoverBoundingRect = ref.current?.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
      moveCard(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.
      item.index = hoverIndex;
    }
  });
  const [{ isDragging }, drag] = useDrag({
    type: ItemTypes.CARD,
    item: () => {
      return { id, index };
    },
    collect: (monitor) => ({
      isDragging: monitor.isDragging()
    })
  });
  const opacity = isDragging ? 0 : 1;
  drag(drop(ref));
  return (
    <div
      className={type}
      ref={ref}
      style={{ ...style, opacity }}
      data-handler-id={handlerId}
    >
      <div style={{ paddingBottom: '15px' }}> 
        {text}
      </div>
      {children}
    </div>
  );
};

I tried to drag the Field one group one item from Group 1 but the ref.current shows group 1 as a dragging item. The below image illustrates the ref.current gives Group 1 but was dragged the Field one group one item enter image description here

Working demo available here. Any help on this is really helpful for me.

note: I have been using React DnD for drag and drop hence need to use this for group items and sub-group items, can't switch to other libraries which might conflict with the existing react dnd.

I can track it while sorting it by using if (!monitor.isOver({ shallow: true })) return; and the ref.current gives correct item while sorting. sandbox updated. The question is when I drag some new item over the already dropped item, the ref.current gives group as a drag item when hovering the fields inside the group. How to get a current item while hovering on it?

user0227
  • 113
  • 1
  • 2
  • 7

0 Answers0