0

I'm desperately trying to have a custom drag handle INSIDE of draggable children of a grid using react, typescript and react-beautiful-dnd. Any ideas on how i can achieve that? This is pretty much what the idea is enter image description here

This is my grid component code. I took the example shown in the codepens and tutorials. But any help would be greatly appreciated :)

import React, { ReactNode, useState } from "react";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
import ChildComponent1 from "../components/ChildComponent1";
import ChildComponent2 from "../components/ChildComponent2";
import ChildComponent3 from "../components/ChildComponent3";
import ChildComponent4 from "../components/ChildComponent4";

interface ItemProps {
  id: string;
  content: ReactNode;
}

interface ColumnProps {
  id: string;
  title: string;
  itemIds: string[];
}

interface GridDataProps {
  items: Record<string, ItemProps>;
  columns: Record<string, ColumnProps>;
  columnOrder: string[];
}

const gridData: GridDataProps = {
  items: {
    'item-1': { id: 'item-1', content: <ChildComponent1/> },
    'item-2': { id: 'item-2', content: <ChildComponent2/> },
    'item-3': { id: 'item-3', content: <ChildComponent3/> },
    'item-4': { id: 'item-4', content: <ChildComponent4/> },
  },
  columns: {
    'column-1': {
      id: 'column-1',
      title: 'To do',
      itemIds: ['item-1', 'item-2'],
    },
    'column-2': {
      id: 'column-2',
      title: 'bla',
      itemIds: ['item-3', 'item-4'],
    },
  },
  columnOrder: ['column-1', 'column-2'],
};


function DashboardGrid() {
  const [state, setState] = useState(gridData);

  const onDragEnd = (result: any) => {
    const { destination, source, draggableId } = result;

    if (!destination) {
      return;
    }

    if (
      destination.droppableId === source.droppableId &&
      destination.index === source.index
    ) {
      return;
    }

    const start = state.columns[source.droppableId];
    const finish = state.columns[destination.droppableId];

    if (start === finish) {
      const newItemIds = Array.from(start.itemIds);
      newItemIds.splice(source.index, 1);
      newItemIds.splice(destination.index, 0, draggableId);

      const newColumn = {
        ...start,
        itemIds: newItemIds,
      };

      const newState = {
        ...state,
        columns: {
          ...state.columns,
          [newColumn.id]: newColumn,
        },
      };

      setState(newState);
      return;
    }

    // Moving from one list to another
    const startitemIds = Array.from(start.itemIds);
    startitemIds.splice(source.index, 1);
    const newStart = {
      ...start,
      itemIds: startitemIds,
    };

    const finishitemIds = Array.from(finish.itemIds);
    finishitemIds.splice(destination.index, 0, draggableId);
    const newFinish = {
      ...finish,
      itemIds: finishitemIds,
    };

    const newState = {
      ...state,
      columns: {
        ...state.columns,
        [newStart.id]: newStart,
        [newFinish.id]: newFinish,
      },
    };

    setState(newState);
  };

  return (
    <section className="dashBoardSectiondGrid">

      <div className="dashboardSectionGridButtonContainer">

        <Button
          title="Reset grid layout"
          text="Reset"
          icon={<RotateCcw/>}
        />

      </div>

      <DragDropContext onDragEnd={onDragEnd}>

        <section className="sectionGrid">

          {state.columnOrder.map((columnId, index) => {
            const column = state.columns[columnId];
            const items = column.itemIds.map(itemId => state.items[itemId]);

            return (
              <div className="sectionGridColumn">

                <Droppable droppableId={columnId} key={columnId}>

                  {(provided) => (
                    <div
                      {...provided.droppableProps}
                      ref={provided.innerRef}
                      className="sectionGridColumnItem"
                    >
                      {items.map((item, index) => (
                        <Draggable key={item.id} draggableId={item.id} index={index}>
                          {(provided) => (
                            <div
                              className="sectionGridItem"
                              {...provided.draggableProps}
                              ref={provided.innerRef}
                            >
                              //drag handle should not be here
                              {provided.dragHandleProps && (
                                <div {...provided.dragHandleProps}><DragHandle /></div>
                              )}
                              //
                              {item.content}

                            </div>
                          )}
                        </Draggable>
                      ))}
                    </div>
                  )}
                </Droppable>

              </div>

            )})}

        </section>

      </DragDropContext>

    </section>
  );
}

export default DashboardGrid;
Franke
  • 13
  • 4

0 Answers0