Библиотека Shopify Draggable предоставляет мощный и гибкий инструмент для реализации перетаскиваемых элементов на веб-страницах. Один из ключевых сценариев — работа с динамически добавляемыми элементами, когда набор draggable-элементов изменяется во время выполнения приложения.
При стандартной инициализации Draggable создается экземпляр для набора существующих элементов:
import { Draggable } from '@shopify/draggable';
const draggable = new Draggable(document.querySelectorAll('.draggable-item'), {
draggable: '.draggable-item'
});
Если новые элементы добавляются в DOM после инициализации, они
не станут автоматически draggable. Необходимо обновить
или пересоздать экземпляр Draggable, либо использовать метод
addContainer.
addContainer для новых элементовМетод addContainer позволяет подключить новый контейнер
с элементами к существующему экземпляру Draggable:
const newContainer = document.querySelector('#new-container');
draggable.addContainer(newContainer);
Все элементы внутри #new-container, соответствующие
селектору draggable, становятся частью drag-and-drop логики
без полной перезагрузки Draggable.
Иногда удобнее уничтожить текущий экземпляр и создать новый с обновленным списком элементов:
draggable.destroy();
const allItems = document.querySelectorAll('.draggable-item');
const newDraggable = new Draggable(allItems, {
draggable: '.draggable-item',
delay: 100
});
Это особенно полезно, когда новые элементы добавляются динамически в разные контейнеры или меняются настройки (например, класс draggable или задержка drag).
Draggable поддерживает стандартные события, такие как
drag:start, drag:move, drag:stop,
а также sortable:sorted. Для динамических элементов их
обработка требует делегирования событий:
draggable.on('drag:start', (event) => {
console.log('Начало перетаскивания:', event.source);
});
draggable.on('sortable:sorted', (event) => {
console.log('Элемент отсортирован:', event.oldIndex, '→', event.newIndex);
});
После добавления новых элементов через addContainer или
пересоздание экземпляра события автоматически привязываются ко всем
draggable-элементам.
Для динамических списков часто важно сохранять порядок элементов и поддерживать корректные позиции:
sortable:sorted позволяет отслеживать
перемещения и обновлять внутренние данные.Пример обновления данных при добавлении нового элемента:
const container = document.querySelector('#list');
const newItem = document.createElement('div');
newItem.classList.add('draggable-item');
newItem.textContent = 'Новый элемент';
container.appendChild(newItem);
draggable.addContainer(container); // делает новый элемент draggable
draggable.on('sortable:sorted', (event) => {
const items = Array.from(container.children).map(el => el.textContent);
console.log('Обновленный порядок:', items);
});
removeContainer или destroy, чтобы избежать
утечек памяти и некорректных ссылок.Draggable поддерживает вложенные контейнеры, что особенно полезно для динамически добавляемых блоков:
const parentContainer = document.querySelector('#parent');
const childContainer = document.querySelector('#child');
draggable.addContainer(parentContainer);
draggable.addContainer(childContainer);
Теперь элементы из обоих контейнеров можно перетаскивать, а события sortable будут корректно срабатывать для каждого уровня.
Ключевой подход заключается в аккуратном управлении
контейнерами и пересоздании экземпляра Draggable при
значительных изменениях DOM. Методы addContainer и
destroy обеспечивают гибкость для динамических интерфейсов,
сохраняя возможность отслеживания событий и контроля порядка
элементов.
Использование этих инструментов позволяет строить сложные drag-and-drop интерфейсы с динамическими списками, карточками и nested контейнерами, сохраняя высокую отзывчивость и стабильность приложения.