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
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;