onChange и onFilter

SortableJS — мощная библиотека для реализации перетаскивания элементов списков с полной поддержкой drag-and-drop. Среди множества событий, предоставляемых библиотекой, особое значение имеют onChange и onFilter, поскольку они позволяют контролировать изменения порядка элементов и ограничивать действия пользователя на уровне логики приложения.


Событие onChange

Событие onChange вызывается при любом изменении порядка элементов в списке. Оно предоставляет доступ к информации о текущем состоянии элементов, что позволяет динамически обновлять данные, связанные с порядком элементов, например, массив объектов или индексные значения в базе данных.

Основные параметры

new Sortable(listElement, {
    onChange: function(evt) {
        console.log('Элемент перемещен');
        console.log('Элемент:', evt.item);
        console.log('Новый индекс:', evt.newIndex);
        console.log('Старый индекс:', evt.oldIndex);
    }
});
  • evt.item — DOM-элемент, который был перемещен.
  • evt.oldIndex — индекс элемента до перемещения.
  • evt.newIndex — индекс элемента после перемещения.
  • evt.from — родительский контейнер, из которого элемент был перемещен.
  • evt.to — родительский контейнер, в который элемент был перемещен.

Практическое применение

  1. Обновление массива данных: порядок элементов в интерфейсе может отличаться от порядка в массиве данных. Событие onChange позволяет синхронизировать массив с визуальным порядком.
  2. Сохранение состояния на сервере: можно отправлять AJAX-запрос с новой последовательностью элементов, что актуально для систем управления контентом.
  3. Анимация и визуальные эффекты: возможность запускать дополнительные эффекты при перемещении элементов.

Рекомендации по использованию

  • Не следует выполнять тяжёлые операции напрямую внутри onChange, лучше использовать делегирование или debounce.
  • Если элементы перемещаются между списками, важно проверять evt.from и evt.to, чтобы корректно обновлять соответствующие массивы данных.

Событие onFilter

Событие onFilter срабатывает при попытке перетащить или удалить элемент, который помечен как фильтруемый, например с помощью CSS-класса или селектора, определенного в опции filter. Оно позволяет блокировать определённые действия для выбранных элементов.

Настройка фильтра

new Sortable(listElement, {
    filter: '.disabled',
    onFilter: function(evt) {
        console.log('Попытка взаимодействия с фильтруемым элементом');
        console.log('Элемент:', evt.item);
    }
});
  • filter — CSS-селектор или функция, возвращающая true для элементов, которые должны быть заблокированы.
  • evt.item — DOM-элемент, с которым произошло взаимодействие.
  • evt.preventDefault() — можно использовать для предотвращения стандартного действия библиотеки.

Возможности onFilter

  1. Блокировка перемещения отдельных элементов: элементы с определёнными классами не могут быть перемещены.
  2. Обработка специальных действий: можно назначить действия на кнопки внутри элементов, например удаление или редактирование, не влияя на сортировку.
  3. Гибкая логика фильтрации: функция фильтра позволяет реализовать сложные правила, например блокировать перетаскивание для элементов с определённым состоянием.

Пример динамической фильтрации

new Sortable(listElement, {
    filter: function(evtItem) {
        return evtItem.classList.contains('locked');
    },
    onFilter: function(evt) {
        alert('Этот элемент заблокирован для перемещения');
    }
});
  • Функция filter получает текущий элемент и возвращает true, если он заблокирован.
  • В onFilter можно реализовать любые уведомления, логирование или визуальные подсказки.

Взаимодействие onChange и onFilter

Эти события часто используются совместно для полной логики управления списками:

  • onFilter ограничивает возможность перетаскивания определённых элементов.
  • onChange фиксирует только допустимые перемещения, что позволяет поддерживать актуальную последовательность данных.
new Sortable(listElement, {
    filter: '.locked',
    onFilter: function(evt) {
        console.warn('Перемещение заблокировано:', evt.item.textContent);
    },
    onChange: function(evt) {
        console.log('Элемент успешно перемещен:', evt.item.textContent);
    }
});

Такой подход обеспечивает чистое разделение обязанностей: фильтрация контролирует доступ, а изменение порядка фиксирует результат.


Оптимизация работы с событиями

  • Использование делегирования событий внутри onChange и onFilter снижает нагрузку на браузер при большом количестве элементов.
  • Применение debounce при сохранении данных на сервере предотвращает избыточные запросы при быстром перемещении элементов.
  • Чёткое разделение логики фильтрации и обработки изменений позволяет создавать масштабируемые интерфейсы с динамическими списками.

Если требуется, могу подготовить отдельный блок с реальными сценариями использования onChange и onFilter в крупном приложении, включая обновление нескольких списков и интеграцию с базой данных. Это будет выглядеть как полноценный учебный пример с кодом.