Skip to content

Instantly share code, notes, and snippets.

@ambrizals
Last active August 10, 2022 11:08
Show Gist options
  • Save ambrizals/d5c564051d5e7230f9d5db264df82026 to your computer and use it in GitHub Desktop.
Save ambrizals/d5c564051d5e7230f9d5db264df82026 to your computer and use it in GitHub Desktop.
Simple Drag And Drop on React JS
// Demo : https://codesandbox.io/s/test-drag-with-handler-forked-vurlfx?file=/src/App.tsx
import React, { useEffect, useState } from "react";
interface model {
name: string;
hover: boolean;
}
interface category {
name: string;
data: Array<model>;
hover: boolean;
}
const Kuesioner = "kuesioner";
export default function App() {
const [data, setData] = useState<Array<category>>([]);
const [dragStatus, setDragStatus] = useState<boolean>(false);
useEffect(() => {
setData([
{
name: "General 1",
data: [
{ name: "test 1", hover: false },
{ name: "test 2", hover: false }
],
hover: false
},
{
name: "General 2",
data: [
{ name: "test 3", hover: false },
{ name: "test 4", hover: false }
],
hover: false
}
]);
}, []);
const testClick = (data: model, categoryName: string) => {
alert(`Telah di click ${data.name} pada kategori ${categoryName}`);
};
const onDragStart = (
event: React.DragEvent,
categoryIndex: number,
entryIndex: number
) => {
event.dataTransfer.setData(
Kuesioner,
JSON.stringify({
categoryIndex,
entryIndex
})
);
// console.log("drag start");
// setDragStatus(true);
};
const onDragStop = () => {
setDragStatus(false);
const tempData = [...data];
const result = tempData.map((item) => {
const categoryData = item.data.map((item) => {
item.hover = false;
return item;
});
item.data = categoryData;
item.hover = false;
return item;
});
setData(result);
};
const onDrop = (
event: React.DragEvent,
categoryIndex: number,
entryIndex?: number
) => {
const originData: {
categoryIndex: number;
entryIndex: number;
} = JSON.parse(event.dataTransfer.getData(Kuesioner));
const tempData = [...data];
const previousData =
tempData[originData.categoryIndex].data[originData.entryIndex];
tempData[originData.categoryIndex].data.splice(originData.entryIndex, 1);
if (entryIndex !== undefined) {
tempData[categoryIndex].data.splice(entryIndex, 0, previousData);
} else {
tempData[categoryIndex].data.push(previousData);
}
console.log(tempData[originData.categoryIndex]);
// Reset hover status
const result = tempData.map((category) => {
category.hover = false;
const entryData = category.data.map((entry) => {
entry.hover = false;
return entry;
});
category.data = entryData;
return category;
});
setData(result);
setDragStatus(false);
};
const onDragOver = (
handler: React.DragEvent,
targetCategory: number,
targetData?: number
) => {
handler.preventDefault();
setDragStatus(true);
let tempData = [...data];
if (targetData !== undefined) {
const result = tempData.map((category, indexCategory) => {
if (targetCategory === indexCategory) {
if (!category.data[targetData].hover) {
const result = category.data.map((entry, index) => {
if (index === targetData) {
entry.hover = true;
} else {
entry.hover = false;
}
return entry;
});
category.data = result;
category.hover = false;
}
} else {
const result = category.data.map((entry) => {
entry.hover = false;
return entry;
});
category.data = result;
category.hover = false;
}
return category;
});
tempData = result;
} else {
if (!tempData[targetCategory].hover) {
const result = tempData.map((category, index) => {
const resultEntry = category.data.map((entry) => {
entry.hover = false;
return entry;
});
if (targetCategory === index) {
category.hover = true;
} else {
category.hover = false;
}
category.data = resultEntry;
return category;
});
tempData = result;
}
}
setData(tempData);
};
// hover:bg-neutral-100
return (
<div className="App">
<h1>Task Order</h1>
<div className="flex flex-col w-screen justify-start items-strech">
{data.map((category, indexCategory) => (
<div key={indexCategory} className="w-full flex flex-col">
<div className="w-full bg-neutral-200 p-3">{category.name}</div>
{category.data.map((entry, indexEntry) => (
<div
key={indexEntry}
className={`flex border text-left py-4 ${
entry.hover && "bg-neutral-300"
}`}
draggable
onTouchStart={() => console.log("ok")}
onClick={() => testClick(entry, category.name)}
onDragStart={(e) => onDragStart(e, indexCategory, indexEntry)}
onDragEnd={() => onDragStop()}
onDrop={(e) => onDrop(e, indexCategory, indexEntry)}
onDragOver={(e) => onDragOver(e, indexCategory, indexEntry)}
>
<div className="bg-black w-6 m-1 h-auto"></div>
<div>{entry.name}</div>
</div>
))}
{dragStatus && (
<div
className={`flex border text-left py-4 ${
category.hover && "bg-neutral-300"
}`}
onDragOver={(e) => onDragOver(e, indexCategory)}
onDrop={(e) => onDrop(e, indexCategory)}
>
Taruh Disini
</div>
)}
</div>
))}
</div>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment