Хуки и middleware

Gridstack.js предоставляет мощный механизм управления интерактивными сетками, который выходит за рамки простого drag-and-drop. Одной из ключевых возможностей являются хуки и middleware, позволяющие вмешиваться в процесс работы сетки, изменять поведение виджетов и управлять событиями до и после их выполнения.


Хуки: концепция и назначение

Хуки (hooks) — это функции, которые вызываются в определенные моменты жизненного цикла сетки или отдельных виджетов. Они дают возможность:

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

Примеры событий, для которых можно использовать хуки:

  • beforeDragStart — вызывается перед началом перетаскивания виджета;
  • beforeDrop — вызывается перед добавлением нового элемента на сетку;
  • change — вызывается после завершения изменения позиции или размера виджета.

Синтаксис добавления хука:

const grid = GridStack.init({ /* опции */ });

grid.on('beforeDragStart', function(event, el) {
    console.log('Начало перетаскивания', el);
    // Можно вернуть false, чтобы отменить действие
});

Особенности хуков:

  • Возврат false в хуке обычно блокирует стандартное действие сетки.
  • Хуки могут использоваться для валидации данных или ограничения перемещений.
  • Для сложной логики можно комбинировать несколько хуков для одного события.

Middleware: промежуточная логика обработки

Middleware в Gridstack.js — это функции, которые обрабатывают данные между источником события и конечной реакцией сетки. Они полезны для интерцептации изменений и модификации поведения по умолчанию.

Основные отличия от хуков:

  • Middleware получают данные и могут их изменять, прежде чем они попадут в сетку;
  • Они вызываются в цепочке, что позволяет создавать несколько уровней обработки;
  • Middleware не обязательно блокируют событие, но могут его корректировать.

Пример middleware для обработки перемещений:

grid.engine.addMoveMiddleware((el, newPos) => {
    // newPos содержит {x, y, w, h}
    if (newPos.x < 0) newPos.x = 0; // запрещаем отрицательные координаты
    if (newPos.y < 0) newPos.y = 0;
    return newPos; // возвращаем откорректированные координаты
});

Применение middleware:

  • Ограничение размеров или позиций виджетов;
  • Автоматическое выравнивание элементов сетки;
  • Синхронизация состояния сетки с внешними источниками данных.

Различие между хуками и middleware

Хуки Middleware
Вызываются в момент события Обрабатывают данные перед применением
Могут отменять действие (return false) Могут модифицировать данные и передавать их дальше
Обычно реагируют на уже произошедшие события Интерцептируют событие до его применения
Применяются через grid.on Применяются через grid.engine.add*Middleware

Примеры комбинации хуков и middleware

Сценарий: ограничение перемещения виджетов в пределах верхней половины сетки и логирование всех изменений.

grid.engine.addMoveMiddleware((el, pos) => {
    if (pos.y > grid.opts.maxRows / 2) pos.y = grid.opts.maxRows / 2;
    return pos;
});

grid.on('change', (event, items) => {
    items.forEach(item => {
        console.log(`Виджет ${item.id} перемещён в (${item.x}, ${item.y})`);
    });
});

В этом примере middleware контролирует позицию до применения, а хук change позволяет реагировать уже после завершения действия.


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

  • Всегда возвращайте корректные данные из middleware, иначе сетка может некорректно перерисоваться.
  • Для сложной логики используйте цепочки middleware — это облегчает поддержку кода.
  • Хуки удобны для валидации, логирования и реакций на завершённые действия.
  • Не смешивайте логику отмены действия и модификации данных в одном хуке — это может приводить к непредсказуемым результатам.

Совместное использование хуков и middleware

Gridstack.js проектировался так, чтобы хуки и middleware дополняли друг друга:

  • Middleware корректируют данные до применения;
  • Хуки реагируют на события после применения, позволяя выполнять побочные эффекты, уведомления или синхронизацию с сервером.

Такое разделение обязанностей делает систему гибкой и расширяемой, особенно при работе с динамическими и интерактивными дашбордами.