Для начала работы с Dragula требуется подключить библиотеку. Наиболее распространённые способы:
Через CDN:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.3/dragula.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.3/dragula.min.js"></script>
Через npm:
npm install dragula
import dragula from 'dragula';
import 'dragula/dist/dragula.css';
После подключения библиотека предоставляет функцию
dragula(), которая инициализирует возможность
перетаскивания элементов между контейнерами.
Dragula позволяет реализовать drag-and-drop между контейнерами, сохраняя гибкость настройки. Основные моменты:
Простейшая инициализация:
const containers = [document.getElementById('left'), document.getElementById('right')];
const drake = dragula(containers);
Для отправки изменений на сервер необходимо отслеживать события перемещения элементов. Ключевые события:
drop — элемент перемещён в новый контейнер.remove — элемент удалён из контейнера.dragend — завершение перетаскивания (независимо от
результата).Пример обработки события drop:
drake.on('drop', (el, target, source, sibling) => {
const data = {
itemId: el.dataset.id,
fromContainer: source.id,
toContainer: target.id,
position: Array.from(target.children).indexOf(el)
};
fetch('/update-position', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(result => console.log('Сервер подтвердил:', result))
.catch(error => console.error('Ошибка при отправке данных:', error));
});
Пояснения ключевых моментов:
el.dataset.id — уникальный идентификатор перемещаемого
элемента.source.id и target.id — идентификаторы
контейнеров для отслеживания перемещения.position — индекс элемента в новом контейнере, что
важно для восстановления порядка на сервере.Если требуется отправлять изменения пакетно, можно накапливать изменения в массив:
let changes = [];
drake.on('drop', (el, target, source, sibling) => {
changes.push({
itemId: el.dataset.id,
from: source.id,
to: target.id,
position: Array.from(target.children).indexOf(el)
});
});
function sendChanges() {
if (changes.length === 0) return;
fetch('/batch-update', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({changes})
})
.then(() => changes = [])
.catch(error => console.error('Ошибка отправки пакета изменений:', error));
}
Пакетная отправка особенно полезна при работе с списками с большим количеством элементов, чтобы не перегружать сервер множественными запросами.
Dragula предоставляет методы accepts и
invalid для контроля, какие элементы можно перетаскивать и
куда.
Пример:
const drake = dragula(containers, {
moves: (el, source, handle, sibling) => {
return !el.classList.contains('locked');
},
accepts: (el, target, source, sibling) => {
return target.id !== 'archive';
}
});
Использование фильтров важно при отправке изменений на сервер, чтобы не фиксировать неподходящие действия.
Для надежной работы с сервером рекомендуется обрабатывать возможные ошибки:
drake.on('drop', (el, target, source) => {
const payload = { id: el.dataset.id, from: source.id, to: target.id };
fetch('/update', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
})
.then(response => {
if (!response.ok) throw new Error('Сервер вернул ошибку');
return response.json();
})
.catch(err => {
console.error('Не удалось отправить данные:', err);
source.insertBefore(el, source.children[Array.from(source.children).indexOf(el)]);
});
});
Возврат элемента на место при ошибке сервера предотвращает рассинхронизацию интерфейса с базой данных.
Dragula совместим с большинством современных фреймворков: React, Vue, Angular. Важно:
useState и обновлять контейнеры.v-for для генерации списков и
реагировать на изменения массива.Пример для React:
const onD rop = (el, target, source) => {
const itemId = el.dataset.id;
setList(prevList => {
const newList = [...prevList];
// обновление позиции и контейнера
return newList;
});
};
Эти меры обеспечивают согласованность данных и предотвращают ошибки при работе с Dragula в продакшн-окружении.