Implementing a kanban grid with native drag and drop in JavaScript

A kanban grid is based on drag and drop, allowing items to be moved from one column to another. In this article we’ll see how to implement the JavaScript code needed to handle this type of component.

For an element to be draggable and droppable, it must have the draggable attribute set to true. Then, the following DOM events are triggered in sequence:

  1. dragstart: the drag operation begins on the chosen element, which we can access through the target property of the event object; event.dataTransfer.effectAllowed lets us specify the visual effect to use.
  2. dragover: triggered when the dragged element is over another element.
  3. dragend: triggered when the drag operation ends.
  4. drop: triggered when the dragged element is released.

However, these events only control the transfer and release phases. To actually move the chosen element from the source column to the target column in the DOM, we need to:

  1. Mark the chosen element with a special CSS class when the operation begins.
  2. Ignore or block the intermediate events.
  3. On the drop event, select the chosen element, clone it, add it to the target container, and remove it from the DOM in the same operation.

The key point to understand is that these events must be handled at the level of the parent elements of the draggable items, since it’s the grid’s columns (containers) that must be manipulated in the DOM.

So we can write:

function dragItems() {
  document.querySelectorAll('.kanban-items').forEach((container) => {

    container.addEventListener('dragstart', (e) => {
      if (e.target && e.target.classList.contains('kanban-item')) {
        e.target.classList.add('dragged');
        e.dataTransfer.effectAllowed = 'move';
      }
    });

    container.addEventListener('dragend', (e) => {
        e.preventDefault();
    });

    
    container.addEventListener('dragover', (e) => {
      e.preventDefault();
    });

    
    container.addEventListener('drop', (e) => {
      const draggedEl = document.querySelector('.dragged'); 
      if (draggedEl) {
         const copy = draggedEl.cloneNode(true);
         container.appendChild(copy);
         draggedEl.remove();
      }
      e.preventDefault();
    });
  });
}

The cloneNode() method is used here to copy the dragged element along with any possible events associated with it. Once copied and inserted into the column/container handling the drop event, the original element can be removed from the DOM.

Demo

JavaScript Kanban

Conclusion

This type of component allows us to leverage JavaScript’s native drag and drop API to implement the main functionality of a kanban grid.

Back to top