Combined: sortable with inline editing
Problem
Your list items need to be both reorderable by drag and editable inline by click. The two interaction modes conflict: a click that starts an edit must not be interpreted as the beginning of a drag.
Solution
A list where items can be reordered by drag and inline-edited:
ts
import { createSortable } from '@vielzeug/dragit';
let items = [
{ id: '1', label: 'Design' },
{ id: '2', label: 'Develop' },
{ id: '3', label: 'Deploy' },
];
function render() {
listEl.innerHTML = items
.map(
(item) => `
<li data-sort-id="${item.id}">
<span class="handle">⠿</span>
<input value="${item.label}" data-item-id="${item.id}" />
</li>
`,
)
.join('');
sortable.sync();
}
const sortable = createSortable({
element: listEl,
handle: '.handle',
onReorder: (ids) => {
items = ids.map((id) => items.find((i) => i.id === id)!);
saveItems(items);
},
});
render();Pitfalls
- A
pointerdownevent starts a drag by default. Guard inline-edit activation behind an explicit handle element or a long-press delay so a short click doesn't trigger a drag. - Avoid calling
sortable.sync()while a drag is in progress. Re-render afteronDragEndif your UI rebuilds the list. - Ensure the edit button calls
e.stopPropagation()so a click on the button does not propagate to the item's drag listener.