Интеграция с серверным хранилищем

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


Формат хранения данных

Gridstack.js использует JSON-структуры для представления состояния сетки. Каждая карточка (widget) описывается объектом со следующими свойствами:

  • x — горизонтальная позиция (колонка) в сетке
  • y — вертикальная позиция (ряд)
  • width (w) — ширина виджета в ячейках
  • height (h) — высота виджета в ячейках
  • id — уникальный идентификатор виджета
  • Дополнительные пользовательские свойства, например content или type, для хранения специфической информации

Пример структуры JSON для трех виджетов:

[
  { "id": "widget1", "x": 0, "y": 0, "w": 2, "h": 2, "content": "График продаж" },
  { "id": "widget2", "x": 2, "y": 0, "w": 2, "h": 3, "content": "Таблица заказов" },
  { "id": "widget3", "x": 0, "y": 2, "w": 4, "h": 2, "content": "Календарь событий" }
]

События для синхронизации

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

  • change — вызывается при любом изменении положения или размера виджета
  • added — при добавлении нового виджета
  • removed — при удалении виджета

Эти события можно использовать для отправки обновленных данных на сервер.

const grid = GridStack.init({/* настройки сетки */});

grid.on('change', function(event, items) {
    const layout = grid.save(); // получает текущий JSON-состояние
    fetch('/api/saveLayout', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(layout)
    });
});

В примере выше grid.save() возвращает массив всех виджетов с их координатами и размерами, который затем отправляется на сервер методом POST.


Загрузка состояния с сервера

Для восстановления состояния сетки при загрузке страницы используется метод load():

fetch('/api/getLayout')
    .then(response => response.json())
    .then(data => {
        grid.load(data); // восстанавливает расположение виджетов
    });

Важно обеспечить уникальные идентификаторы виджетов (id), чтобы Gridstack мог корректно соотнести серверные данные с конкретными элементами DOM.


Обработка добавления и удаления виджетов

При динамическом добавлении виджетов через интерфейс необходимо:

  1. Генерировать уникальный id для нового виджета.
  2. Добавлять виджет с использованием grid.addWidget():
const node = { id: 'widget4', x: 0, y: 0, w: 2, h: 2, content: 'Новый график' };
grid.addWidget(`<div id="${node.id}">${node.content}</div>`, node);
  1. Сохранять изменения на сервере после добавления:
grid.on('added', function(event, items) {
    const layout = grid.save();
    fetch('/api/saveLayout', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(layout)
    });
});

Удаление виджетов аналогично: используется событие removed и метод grid.removeWidget(element).


Оптимизация взаимодействия с сервером

  • Дебаунс отправки: при частых перемещениях виджетов целесообразно использовать дебаунс, чтобы не перегружать сервер.
  • Минимальные изменения: вместо отправки полного состояния можно отправлять только измененные элементы.
  • Версионирование: добавление поля version к JSON позволяет управлять конфликтами при одновременном редактировании сетки несколькими пользователями.
let saveTimeout;
grid.on('change', function() {
    clearTimeout(saveTimeout);
    saveTimeout = setTimeout(() => {
        fetch('/api/saveLayout', { method: 'POST', body: JSON.stringify(grid.save()) });
    }, 300);
});

Работа с различными серверными технологиями

Gridstack.js универсален и может интегрироваться с любыми бекенд-сервисами, поддерживающими HTTP-запросы и JSON:

  • Node.js + Express — простая маршрутизация API и хранение в MongoDB или SQLite
  • PHP + MySQL — прием POST-запросов и сериализация JSON в базу данных
  • Python (Django, Flask) — десериализация JSON и сохранение модели виджета в базе

Пример обработки на Node.js + Express:

app.post('/api/saveLayout', (req, res) => {
    const layout = req.body;
    database.saveLayout(layout) // функция сохранения в БД
        .then(() => res.send({ status: 'ok' }))
        .catch(err => res.status(500).send({ error: err.message }));
});

Хранение дополнительных данных

Помимо координат и размеров, в серверное хранилище можно передавать:

  • Цветовые схемы и стили виджетов
  • Фильтры и настройки графиков
  • Историю изменений для восстановления предыдущих версий

Для этого достаточно расширять JSON-объект виджета дополнительными ключами:

{ "id": "widget1", "x": 0, "y": 0, "w": 2, "h": 2, "content": "График продаж", "color": "#3498db", "filters": { "region": "EU" } }

Итоговые рекомендации по интеграции

  • Всегда использовать уникальные id для виджетов.
  • Сохранять состояние сетки в JSON на сервере после ключевых событий (change, added, removed).
  • Обеспечивать восстановление состояния через grid.load().
  • Применять дебаунс или минимизацию данных при частых изменениях.
  • Расширять JSON для хранения любых дополнительных настроек виджетов.

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