javascriptadvanced60 minutes

Build a Dynamic Kanban Board with Drag-and-Drop in JavaScript

Create a fully functional Kanban board application that supports adding, moving, and editing tasks across multiple columns using native JavaScript and the Drag-and-Drop API.

Challenge prompt

Build a Kanban board app with at least three columns (e.g., To Do, In Progress, Done). Users should be able to add new tasks, edit existing tasks inline, and move tasks between columns using drag-and-drop functionality. The board's state should persist in localStorage, so refreshing the page retains the current tasks and their column positions.

Guidance

  • Structure your application using modular functions or ES6 classes to manage the board and tasks cleanly.
  • Utilize the HTML5 Drag and Drop API for intuitive task moving with proper drag event handling.
  • Implement localStorage to save and retrieve tasks and their states on page load.
  • Ensure accessibility by allowing keyboard navigation and providing clear visual feedback during dragging.

Hints

  • Use data attributes to track task ids and their current column during drag events.
  • Debounce or throttle save operations to localStorage to optimize performance during frequent updates.
  • Use event delegation for handling clicks and edits within dynamically created task elements.

Starter code

class KanbanBoard {
  constructor(containerId) {
    this.container = document.getElementById(containerId);
    this.columns = ['To Do', 'In Progress', 'Done'];
    this.tasks = {};
    this.loadTasks();
    this.render();
    this.addEventListeners();
  }

  loadTasks() {
    const saved = localStorage.getItem('kanbanTasks');
    this.tasks = saved ? JSON.parse(saved) : {
      'To Do': [],
      'In Progress': [],
      'Done': []
    };
  }

  saveTasks() {
    localStorage.setItem('kanbanTasks', JSON.stringify(this.tasks));
  }

  render() {
    this.container.innerHTML = '';
    this.columns.forEach(column => {
      const colDiv = document.createElement('div');
      colDiv.className = 'column';
      colDiv.dataset.column = column;
      colDiv.innerHTML = `<h2>${column}</h2><div class='task-list'></div><button>Add Task</button>`;
      this.container.appendChild(colDiv);
      const taskList = colDiv.querySelector('.task-list');
      this.tasks[column].forEach(task => {
        const taskEl = document.createElement('div');
        taskEl.className = 'task';
        taskEl.textContent = task.text;
        taskEl.draggable = true;
        taskEl.dataset.id = task.id;
        taskList.appendChild(taskEl);
      });
    });
  }

  addEventListeners() {
    // Implement drag, drop, add and edit logic here
  }
}

// Usage
// const board = new KanbanBoard('kanbanContainer');

Expected output

A dynamic Kanban board with three columns. Users can add new tasks to any column by clicking 'Add Task', edit tasks inline by clicking on the task text, and drag tasks between columns. The state remains consistent after refreshing the page.

Core concepts

Drag and Drop APIlocalStorage persistenceDOM manipulationEvent handlingData structures

Challenge a Friend

Send this duel to someone else and see if they can solve it.