Drag and Drop starter project with ReactJS - Part 2
Vedant Nandoskar
Posted on April 29, 2021
Hello fellow developers,
This post is a continuation of the series Drag and Drop Starter Project with ReactJS. In this series, I will walk you people through building a starter project for drag and drop feature in ReactJS without using any external library. Drag and drop features are used in a lot of projects, such as site builders, drawing apps, applications where user can customize their screen, and many more.
In part one, we built
- Drag and drop UI components
- Custom styled our components
- A basic drag and drop feature
You can re-visit Part One of the series here
By the end of part 1, you should be having the following screen,
In this part we would be,
- Making components redraggable
- Adding feature to remove elements
Let's get onto it!
1. Making components redraggable
To make the components redraggable, we need to know the id
of the component being dragged. For this, we need to update our dragStart
class method in the App component.
//App.js
...
dragStart = (ev, type, redrag=false, elementId=null) => {
ev.dataTransfer.setData("type", type);
if (redrag) {
ev.dataTransfer.setData("elementId", elementId);
}
}
...
This would set the current dragging element's ID in the dataTransfer
attribute of the drag event.
Now we need to make two changes in the getElementList
utility function we created earlier. We need to pass this function as a parameter, and need to update the HTML to make them draggable and to accommodate this updated function.
//utility.js
const getElementList = (elementData, dragStartHandler) => {
const elements = [];
Object.keys(elementData).forEach(key => {
let { type, left, top } = elementData[key];
switch (type) {
case 'blue':
elements.push(
<div
className="component blue"
key={key}
style={{
position: 'absolute',
left: left + 'px',
top: top + 'px',
zIndex: 100,
}}
draggable={true}
onDragStart={(ev) => { dragStartHandler(ev, type, true, key); }}
>
Blue Component
</div>
);
break;
case 'green':
elements.push(
<div
className="component green"
key={key}
style={{
position: 'absolute',
left: left + 'px',
top: top + 'px',
}}
draggable={true}
onDragStart={(ev) => { dragStartHandler(ev, type, true, key); }}
>
Green Component
</div>
);
break;
case 'purple':
elements.push(
<div
className="component purple"
key={key}
style={{
position: 'absolute',
left: left + 'px',
top: top + 'px',
}}
draggable={true}
onDragStart={(ev) => { dragStartHandler(ev, type, true, key); }}
>
Purple Component
</div>
);
break;
default:
break;
}
});
return elements;
}
export { getElementList };
Now, finally, we need to update the drop class method in App component. We need to capture the element's ID if it exists, and then update the "X" and "Y" co-ordinates of that element.
//App.js
...
drop = (ev) => {
ev.preventDefault();
const type = ev.dataTransfer.getData("type");
const { elementData } = this.state;
let { nextElementId } = this.state;
const newElementData = {
type,
left: ev.clientX,
top: ev.clientY,
}
let elementId = ev.dataTransfer.getData("elementId");
if (elementId) { // check if element is redragged and the ID exists in dataTransfer
elementId = parseInt(elementId);
elementData[elementId] = {
...elementData[elementId],
left: ev.clientX,
top: ev.clientY,
}
parseInt(ev.dataTransfer.getData("elementId"))
} else {
elementData[nextElementId] = newElementData;
nextElementId = nextElementId + 1;
}
ev.dataTransfer.clearData();
this.setState({
elementData,
nextElementId,
});
}
...
When you run this and visit the browser, you should be able to re-drag the components
We now have added the ability to re-drag and re-arrange the components in our app.
2. Remove or delete the components
We can add the feature to remove the components from the Drop Area when they are dragged outside of it. This is a relatively simple feature since most of the things are already setup.
First, we create a new class method in the App component, named dropOutside
, which would handle removing the element's data from the state. This is done by retrieving the dragged element's ID and removing that entry from the elementData
in the App component's state.
//App.js
...
dropOutside = (ev) => {
const { elementData } = this.state;
let elementId = ev.dataTransfer.getData("elementId");
if (elementId && elementData[elementId]) {
delete elementData[elementId];
}
ev.dataTransfer.clearData();
this.setState({
elementData,
});
}
...
Now we add this method to the onDrop
attribute of the Components List div (the left side div).
//App.js
...
<div className="components-list" onDrop={this.dropOutside} onDragOver={this.dragOver}>
...
And we're done with it. When the page updates in the browser, you should be able to delete the elements from the Drop Area when you drag them outside of it.
Alright then, that's it from me for now hope it was helpful. Feel free to drop any questions in the comments section!
Code Hosted at
Vedant1202 / Drag-and-Drop-Starter-
A starter project for creating drag and drop feature in ReactJS
Demo hosted at Drag and Drop Starter Demo
You can follow me on my [Dev.to @vedant1202]
and on my Github@Vedant1202
Peace and stay safe ✌️
Footnotes
Cover image taken from Photo by Mimi Thian on Unsplash
References from Mozilla Developer Network Web Documentation
Posted on April 29, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.