Creare una dashboard con il drag and drop dei widget in JavaScript

In questo articolo mostreremo l'implementazione di una dashboard minimale in cui i widget aggiunti possono essere trascinati sulla griglia visuale.

La teoria

Per essere trascinabile tramite il drag and drop nativo un elemento deve avere l'attributo draggable impostato su true. Quando il trascinamento inizia, viene innescato l'evento dragstart. Va subito chiarito un concetto fondamentale: questo evento, e gli altri che vedremo, vengono gestiti sull'elemento genitore dell'elemento trascinato.

Quindi event.target contiene un riferimento DOM all'elemento che viene trascinato. Nella fase iniziale del trascinamento possiamo marcare questo elemento con una classe CSS speciale che poi rimuoveremo una volta terminato il trascinamento. Gli eventi interessati sono:

  • dragstart: l'operazione di trascinamento ha inizio sull'elemento scelto a cui possiamo accedere tramite la proprietà target dell'oggetto event; event.dataTransfer.effectAllowed ci permette di specificare l'effetto visuale che verrà usato.
  • dragover: si innesca quando l'elemento scelto si trova sopra un altro elemento.
  • dragend: si innesca quando il trascinamento è terminato.
  • drop: si innesca quando l'elemento scelto viene rilasciato.

Tuttavia, questi eventi controllano solo le fasi del trasferimento e del rilascio, e per far si che l'elemento scelto venga spostato nell'area di destinazione a livello DOM, dobbiamo:

  1. Marcare l'elemento scelto con una classe CSS speciale quando l'operazione ha inizio.
  2. Ignorare o bloccare gli eventi intermedi.
  3. Sull'evento drop, selezionare l'elemento scelto, clonarlo e aggiungerlo al contenitore di destinazione, rimuovendolo dal DOM all'interno della stessa operazione. Poichè l'elemento clonato ha ancora la classe CSS speciale, dobbiamo rimuoverla in modo da avere un unico elemento per operazione.

Il codice

 function dragWidgets(wrapper = null) {
    if (!wrapper) {
      return;
    }
    const containers = wrapper.querySelectorAll('.dashboard-content-area');
    wrapper.addEventListener('dragstart', (e) => {
        
        if (e.target && e.target.classList.contains('dashboard-widget')) {
          e.target.classList.add('dragged');
          e.dataTransfer.effectAllowed = 'move';
        }
      });
    for (const container of containers) {
      

      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);
          copy.classList.remove('dragged');
          container.appendChild(copy);
          draggedEl.remove();
        }
        e.preventDefault();
      });
    }
  }

Demo

JavaScript Dashboard

Conclusione

Questo tipo di layout ci permette di applicare il drag and drop nativo di JavaScript per implementare una funzionalità principale della GUI.

Torna su