Создание связанных списков

SortableJS — мощная библиотека для реализации функционала перетаскивания элементов списка (drag-and-drop) в веб-приложениях на JavaScript. Она позволяет не только сортировать элементы внутри одного списка, но и создавать связанные списки, где элементы можно переносить между разными контейнерами с сохранением порядка и реакцией на события.


Инициализация нескольких списков

Для создания связанных списков требуется инициировать Sortable на каждом контейнере. Ключевой момент — указание общего group. Это позволяет элементам свободно перемещаться между списками, принадлежащими одной группе.

const listA = document.getElementById('listA');
const listB = document.getElementById('listB');

Sortable.create(listA, {
  group: 'shared',   // Группа, объединяющая списки
  animation: 150,    // Плавная анимация перемещения
  ghostClass: 'sortable-ghost', // CSS-класс для элемента во время перетаскивания
});

Sortable.create(listB, {
  group: 'shared',
  animation: 150,
  ghostClass: 'sortable-ghost',
});

Ключевые моменты:

  • group может быть строкой (одна группа) или объектом для более гибкой настройки.
  • animation делает перемещение элементов визуально более плавным.
  • ghostClass позволяет стилизовать перетаскиваемый элемент.

Гибкая настройка групп

Группы поддерживают расширенные опции через объект:

Sortable.create(listA, {
  group: {
    name: 'shared',
    pull: 'clone',    // Элемент копируется при переносе
    put: true         // Разрешение на вставку элементов из других списков
  },
  animation: 150
});

Разбор опций:

  • pull: true | false | 'clone' Управляет поведением при перетаскивании.

    • true — элемент можно переносить.
    • 'clone' — создается копия элемента, оригинал остаётся на месте.
  • put: true | false | [имена групп] Разрешает вставку элементов из других групп. Можно указать массив групп, чтобы разрешить выборочно.


Отслеживание событий

SortableJS предоставляет множество событий для работы со связанными списками:

  • onAdd — срабатывает, когда элемент добавлен в список.
  • onRemove — элемент удален из текущего списка.
  • onUpdate — элемент изменил позицию внутри текущего списка.
  • onEnd — завершается процесс перетаскивания.

Пример использования:

Sortable.create(listB, {
  group: 'shared',
  animation: 150,
  onAdd: function (evt) {
    console.log('Элемент добавлен:', evt.item);
  },
  onRemove: function (evt) {
    console.log('Элемент удалён:', evt.item);
  },
  onUpdate: function (evt) {
    console.log('Порядок изменён внутри списка:', evt.to);
  }
});

Эти события позволяют динамически обновлять данные на сервере, менять состояние интерфейса или производить анимации.


Синхронизация данных

При работе с связанными списками важно поддерживать актуальность данных. Стандартная практика — использовать массивы, представляющие элементы каждого списка:

let dataA = ['Элемент 1', 'Элемент 2'];
let dataB = ['Элемент 3', 'Элемент 4'];

function updateData(evt) {
  const fromList = evt.from.id === 'listA' ? dataA : dataB;
  const toList = evt.to.id === 'listA' ? dataA : dataB;

  const movedItem = fromList.splice(evt.oldIndex, 1)[0];
  toList.splice(evt.newIndex, 0, movedItem);

  console.log('Списки после перемещения:', dataA, dataB);
}

Sortable.create(listA, {
  group: 'shared',
  onEnd: updateData
});

Sortable.create(listB, {
  group: 'shared',
  onEnd: updateData
});

Преимущества такой схемы:

  • Полный контроль над порядком элементов.
  • Возможность синхронизации с сервером через API.
  • Лёгкая интеграция с фреймворками вроде React или Vue.

Дополнительные возможности для связанных списков

  1. Фильтрация элементов Исключение определённых элементов из перетаскивания:

    filter: '.non-draggable',
    preventOnFilter: true

    Элементы с классом .non-draggable будут статичными.

  2. Кастомные анимации Используя CSS и классы ghostClass, chosenClass, dragClass можно создавать уникальные визуальные эффекты.

  3. Перетаскивание по условию Возможность динамически включать или отключать перемещение через disabled:

    sortable.option("disabled", true);
  4. Сложные иерархические списки В связке с плагинами или собственным кодом можно создавать вложенные списки с поддержкой drag-and-drop между уровнями.


Практическая структура HTML для связанных списков

<ul id="listA" class="sortable-list">
  <li>Элемент 1</li>
  <li>Элемент 2</li>
</ul>

<ul id="listB" class="sortable-list">
  <li>Элемент 3</li>
  <li>Элемент 4</li>
</ul>

Стилизация может включать:

.sortable-list {
  border: 1px solid #ccc;
  padding: 10px;
  min-height: 50px;
  width: 200px;
  list-style: none;
}

.sortable-ghost {
  opacity: 0.4;
}

Такой подход создаёт чёткую визуальную и функциональную структуру, позволяющую реализовать полные возможности связанных списков.


Этот метод организации позволяет создавать динамичные интерфейсы с перемещаемыми элементами между разными контейнерами, при этом сохраняя контроль над данными и стилями.