Drag and Drop in LWC (Lightning Web Component)

This post will walk you through the implementation to Drag and Drop in LWC (Lightning Web Component) in the same component. We have to use HTML Drag and Drop API. We can also implement Drag and Drop between multiple Lightning Web Components which you can check here. Let’s get into the implementation.

Implementation

In this implementation, we will create a section to display the list of To-Do Posts in the TO-DO POSTS section. We will be able to drag and drop the To-Do Post into the COMPLETED POSTS section.

To create a Drag and Drop in LWC, first, create a Lightning Web Component upcomingPosts which will have two div tags to display TO-DO POSTS and COMPLETED POSTS. Use the div tag to display multiple To-Do Posts like below in TO-DO POSTS section:

<div id="ToDo2" class="box" draggable="true" ondragstart={drag}>
    Create Dynamic Apex Instance using Type.forName()
</div>

To make the To-Do Post draggable, we have added attribute draggable=”true”. Add attribute ondragstart to handle drag start event which will call the drag method of JS Controller.

We will drag and drop these posts in the COMPLETED POSTS section. To allow the drop functionality on COMPLETED POSTS section, add attribute ondragover which will call the allowDrop method of JS Controller. When an element is dropped, the drop event is called. Add ondrop attribute which will call the drop method of JS Controller.

upcomingPosts.html

<template>
    <lightning-card title="Drag and Drop in Lightning Web Component">
        <lightning-layout>
            <div class="slds-p-around_small">
                <div class="slds-text-heading_small">TO-DO POSTS</div><br/>
                <div class="flex-container">
                    <div id="ToDo2" class="box" draggable="true" ondragstart={drag}>
                        Create Dynamic Apex Instance using Type.forName()
                    </div>
                    <div id="ToDo3" class="box" draggable="true" ondragstart={drag}>
                        Drag and Drop in Lightning Web Component (LWC)
                    </div>
                    <div id="ToDo4" class="box" draggable="true" ondragstart={drag}>
                        Drag and Drop between Multiple Lightning Web Components
                    </div>
                </div>
                <hr></hr>
                <div class="slds-text-heading_small">COMPLETED POSTS</div><br/>
                <div class="flex-container" ondragover={allowDrop} ondrop={drop}>
                    <div id="ToDo1" class="box completed">
                        Share JavaScript Code Between LWC and Aura Component
                    </div>
                </div>
            </div>
        </lightning-layout>
    </lightning-card>
</template>

In JS Controller, the drag() method is called when we grab an element to drag. We will get the Id of an element that we want to drag and use event.dataTransfer.setData() to set the data to transfer. Set the Id of an element to transfer.

By default, data/elements cannot be dropped in other elements. To allow a drop, we must prevent the default handling of the element. The allowDrop() method will call event.preventDefault() to prevent the default behavior.

Finally, the drop() method will be called once the dragged element is dropped. This method will get the Id of element using event.dataTransfer.getData(). Get the element using querySelector() and call the appendChild() method to add the element into the COMPLETED POSTS section.

upcomingPosts.js

import { LightningElement } from 'lwc';
export default class UpcomingPosts extends LightningElement {
    drag(event){
        event.dataTransfer.setData("divId", event.target.id);
    }
    allowDrop(event){
        event.preventDefault();
    }
    drop(event){
        event.preventDefault();
        var divId = event.dataTransfer.getData("divId");
        var draggedElement = this.template.querySelector('#' +divId);
        draggedElement.classList.add('completed'); 
        event.target.appendChild(draggedElement);
    }
}

Here is the CSS that will make this implementation beautiful.

upcomingPosts.css

.box{
    border-radius: 10px;
    background-color: #faf59b;
    padding: 15px;
    width: 148px;
    height: 148px;
    display: inline-block;
    margin: 3px;
    font-size: 15px;
    text-align: center; 
}
.completed{
    background-color: #aafac3;
}
.flex-container {
    display: flex;
    flex-flow: row wrap;
    width: 463px;
}

That is all.

Drag and Drop in LWC

This is how our implementation of Drag and Drop in LWC looks like:

Drag and Drop in LWC
Drag and Drop in LWC

This is how we can implement the functionality to Drag and Drop in LWC (Lightning Web Component). In this implementation, we Dragged and Dropped in the same Lightning Web Component (LWC). We can also drag an element from one Lightning Web Component and drop it into another Lightning Web Component. You can check this implementation here.

If you don’t want to miss a new post, please Subscribe here. If you want to know more about HTML Drag and Drop API, you can check the official documentation here.

Here are some hand-picked implementations for you:

See you in the next implementation. Thanks.

2 thoughts on “Drag and Drop in LWC (Lightning Web Component)”

  1. Hi Nikhil
    As usual very nice post.
    In number of codes, I have seen the use of event.PreventDefault(); and explanation is given as ‘it prevents default behaviour’. What will happen if we miss this line. Is it safe to add this in every place where we add some custom behaviour?
    In your next post for drag and drop between two different LWC can you make it for two way (moving completed posts back to upcoming posts as well).
    I think we need to add ondragover and on drop for flex-container div tag for the TO-DO POSTS and believe the same JS method drop and allowdrop can be utilized. if we use the same method how can be find out if the drag is from todo to completed or from completed to todo so that CSS class completed can be either added or removed.

    1. Yes, event.PreventDefault() is a must else it won’t work. It is used to prevent the default behavior of the respective element.
      I have already written a post for two different LWC. Two-way drag and drop can be implemented in the same way you mentioned. We need to do some additional code to implement drag and drop for two LWC which is explained in the post. You can put extra checks to handle two-way drag and drop properly.

Comments are closed.