События во вложенных сетках

Gridstack.js позволяет создавать гибкие сетки, где одна сетка может содержать другую, формируя вложенные структуры. В таких случаях важно понимать, как события верхнего уровня взаимодействуют с событиями внутренней сетки. Без правильного управления вложенные сетки могут вести себя непредсказуемо: события drag, resize или change могут всплывать в родительскую сетку или игнорироваться.

Вложенная сетка создается внутри элемента родительской сетки. Например:

<div class="grid">
    <div class="grid-stack-item" data-gs-x="0" data-gs-y="0" data-gs-width="6" data-gs-height="6">
        <div class="grid-stack-item-content">
            <div class="nested-grid">
                <!-- Внутренние элементы -->
            </div>
        </div>
    </div>
</div>
const parentGrid = GridStack.init({ /* параметры родительской сетки */ });
const nestedGrid = GridStack.init({ /* параметры вложенной сетки */ }, document.querySelector('.nested-grid'));

Ключевой момент: Gridstack.js различает DOM-элементы родительской и вложенной сетки, поэтому события, такие как change, added, removed, или dragstop, необходимо обрабатывать отдельно для каждой сетки.


Управление событиями вложенной сетки

Gridstack.js предоставляет несколько событий, с которыми стоит работать при вложенных сетках:

  1. added – вызывается при добавлении нового элемента в сетку. Для вложенной сетки важно подписываться на это событие отдельно, иначе изменения родительской сетки не будут учитываться внутренними элементами.

  2. removed – срабатывает при удалении элемента. Если элемент удаляется из вложенной сетки, событие не передается родительской сетке автоматически.

  3. change – отслеживает любое перемещение или изменение размеров элементов. Для вложенной сетки это событие позволяет синхронизировать внутренние элементы и, при необходимости, выполнять корректировку размеров родительских блоков.

  4. dragstart / dragstop – управление перетаскиванием элементов. Для вложенных сеток рекомендуется использовать события drag с дополнительной проверкой target, чтобы исключить случайное срабатывание родительских обработчиков на внутренние элементы:

nestedGrid.on('dragstop', function(event, el) {
    console.log('Элемент вложенной сетки перемещен', el);
});

Предотвращение всплытия событий

По умолчанию события могут “всплывать” из вложенной сетки в родительскую, что иногда приводит к конфликтам. Чтобы этого избежать:

nestedGrid.on('change', function(event, items) {
    event.stopPropagation();
    console.log('Изменения только во вложенной сетке', items);
});

stopPropagation() предотвращает автоматическую обработку события родительской сеткой. Это особенно важно при динамическом изменении размеров элементов или при drag & drop, чтобы родительская сетка не “перехватывала” действия вложенной.


Синхронизация размеров и позиций

Если элементы вложенной сетки изменяют размер, иногда требуется корректировать размеры родительских блоков, чтобы избежать наложений:

nestedGrid.on('change', function(event, items) {
    const parentItem = parentGrid.getGridItems().find(item => item.el.contains(items[0].el));
    parentGrid.update(parentItem.el, { width: calculateWidth(items), height: calculateHeight(items) });
});

Таким образом достигается динамическая адаптация родительской сетки к изменениям во вложенной.


Рекомендации по работе с событиями

  • Всегда инициализировать каждую сетку отдельно, включая вложенные, чтобы события не конфликтовали.
  • Использовать event.stopPropagation() для контроля всплытия.
  • Обрабатывать drag и resize отдельно для родителя и вложенной сетки.
  • При необходимости синхронизировать размеры и положение элементов родительской сетки на основе действий во вложенной.
  • Сохранять ссылку на объект GridStack для каждой сетки, чтобы было удобно обращаться к методам update, removeWidget и addWidget.

Примеры реальных сценариев

  1. Дэшборд с виджетами: родительская сетка содержит виджеты, каждый из которых является вложенной сеткой с графиками. Изменение размеров графиков не должно ломать сетку дэшборда.
  2. Формы с динамическими блоками: каждый блок формы — вложенная сетка. Добавление нового поля должно отражаться только внутри блока, а родительская сетка при этом остаётся стабильной.
  3. Списки задач с подзадачами: родительская сетка — это список проектов, а вложенная — задачи внутри проекта. Перетаскивание задач не должно влиять на соседние проекты.

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