Skip to main content Skip to footer

Adding Drag and Drop Functionality to a Custom Cell

Adding Drag and Drop Functionality to a Custom Cell

Background:

FlexGrid is highly customizable and can work alongside native browser events. While the default behavior of dragging can be toggled with the allowDragging property, implementing custom row reordering using the browsers native drag and drop API gives developers more control over how users interact with their data table.

Steps to Complete:

1. Inject icons into the last column using the formatItem event

2. Add native drag events to handle reordering

3. Reorder the underlying data using collectionView

 

Getting Started:

Inject icons into the last column using the formatItem event

Inside useEffect we use FlexGrid’s formatItem event to insert a group of SVG icons into the last column of each row. One of the icons acts as a visual drag handle.

grid.formatItem.addHandler((s, e) => {
      if (e.panel === s.cells && e.col === s.columns.length - 1) {
        const row = s.rows[e.row];
        const html = `
          <div class="icon-cell" draggable="true" data-index="${e.row}" style="display:flex; gap:10px; cursor:grab;">
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path fill="#ccc" d="M3 17.25V21h3.75l11.06-11.06-3.75-3.75L3 17.25zM21.41 6.34a1.25 1.25 0 000-1.77l-2.98-2.98a1.25 1.25 0 00-1.77 0L14.06 4.1l3.75 3.75 3.6-3.6z"/></svg>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path fill="#ccc" d="M3 6h18v2H3V6zm2 3h14v13H5V9zm5 2v9h2v-9H10zm4 0v9h2v-9h-2z"/></svg>
            <svg class="drag-icon" width="14" height="14" viewBox="0 0 24 24" fill="none"><path fill="#ccc" d="M4 10h2v2H4v-2zm0 4h2v2H4v-2zm0-8h2v2H4V6zm4 0h2v2H8V6zm0 4h2v2H8v-2zm0 4h2v2H8v-2z"/></svg>
          </div>`;
        e.cell.innerHTML = html;
      }
  });

 

Add native drag events to handle reordering

We then enable dragging on the grid’s host element using three native DOM events: dragStart, dragOver, and drop.

grid.hostElement.addEventListener('dragstart', (e) => {
  const target = e.target.closest('.icon-cell');
  if (!target) return;
  e.dataTransfer.setData('text/plain', target.dataset.index);
});
grid.hostElement.addEventListener('dragover', (e) => {
  const row = e.target.closest('.wj-row');
  if (row) e.preventDefault();
});
grid.hostElement.addEventListener('drop', (e) => {
  e.preventDefault();
  const fromIndex = parseInt(e.dataTransfer.getData('text/plain'));
  const toRow = e.target.closest('.wj-row');
  if (!toRow) return;

...
});

These handlers allow a user to drag one row and drop it above or below another. The items are re-ordered directly inside the collectionView, and the grid updates automatically.

 

Reorder the underlying data using collectionView

grid.hostElement.addEventListener('drop', (e) => {
  e.preventDefault();
  const fromIndex = parseInt(e.dataTransfer.getData('text/plain'));
  const toRow = e.target.closest('.wj-row');
  if (!toRow) return;

  const toIndex = Array.from(toRow.parentNode.children).indexOf(toRow);
  const item = cv.items[fromIndex];
  cv.items.splice(fromIndex, 1);
  cv.items.splice(toIndex, 0, item);
  cv.refresh();
});

By combining collectionView, formatItem, and native drag events, this sample enables smooth row reordering in FlexGrid using React. This gives your users intuitive control over data arrangement without requiring third-party drag libraries.

 

You can find this code showcased in this sample application here.

 

Happy coding!

Andrew Peterson

Technical Engagement Engineer