Drag and Drop starter project with ReactJS - Part 2

vedant1202

Vedant Nandoskar

Posted on April 29, 2021

Drag and Drop starter project with ReactJS - Part 2

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,
image
 
In this part we would be,

  1. Making components redraggable
  2. 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);
    }
  }
...
Enter fullscreen mode Exit fullscreen mode

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 };
Enter fullscreen mode Exit fullscreen mode

 
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,
    });
  }

...
Enter fullscreen mode Exit fullscreen mode

 
When you run this and visit the browser, you should be able to re-drag the components
re-drag
 
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,
    });
  }
...
Enter fullscreen mode Exit fullscreen mode

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

...
Enter fullscreen mode Exit fullscreen mode

 
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.
remove-elements

 
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

GitHub logo 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

 

  1. Cover image taken from Photo by Mimi Thian on Unsplash

  2. References from Mozilla Developer Network Web Documentation

💖 💪 🙅 🚩
vedant1202
Vedant Nandoskar

Posted on April 29, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related