Last active
August 10, 2022 11:08
-
-
Save ambrizals/d5c564051d5e7230f9d5db264df82026 to your computer and use it in GitHub Desktop.
Simple Drag And Drop on React JS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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