Кастомные виджеты

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

Кастомный виджет в Gridstack.js — это не просто HTML-элемент, помещённый в сетку, а объект, который может управлять своим состоянием, взаимодействовать с событиями сетки и динамически изменять размеры или позицию.


Структура кастомного виджета

Ключевыми элементами любого виджета являются:

  1. Контейнер виджета Это основной элемент div, который помещается в сетку. Он должен иметь класс grid-stack-item и атрибуты gs-x, gs-y, gs-width, gs-height. Пример базовой структуры:
<div class="grid-stack-item" gs-x="0" gs-y="0" gs-width="2" gs-height="2">
  <div class="grid-stack-item-content">
    <div class="widget-header">Заголовок</div>
    <div class="widget-body">Содержимое</div>
  </div>
</div>
  1. Содержимое виджета Внутри элемента .grid-stack-item-content размещается вся визуальная часть. Здесь можно добавлять кнопки, графики, таблицы или другие интерактивные элементы.

  2. Метаданные виджета Для хранения состояния и конфигурации виджета удобно использовать data- атрибуты или объекты в JS, например:

const widgetData = {
  id: 'widget1',
  type: 'chart',
  options: { color: 'blue', title: 'Продажи' }
};

Инициализация кастомного виджета через Gridstack API

После создания HTML-структуры необходимо интегрировать виджет в сетку. Инициализация выглядит следующим образом:

const grid = GridStack.init({
  column: 12,
  float: true,
  animate: true
});

grid.addWidget('<div class="grid-stack-item" gs-x="0" gs-y="0" gs-width="3" gs-height="3">' +
  '<div class="grid-stack-item-content">Мой кастомный виджет</div></div>');

Для динамического добавления виджетов с разными конфигурациями удобно использовать функцию генерации HTML из JS-объекта:

function createWidget(data) {
  return `<div class="grid-stack-item" gs-x="${data.x}" gs-y="${data.y}" gs-width="${data.width}" gs-height="${data.height}">
            <div class="grid-stack-item-content">
              <div class="widget-header">${data.title}</div>
              <div class="widget-body">${data.content}</div>
            </div>
          </div>`;
}

grid.addWidget(createWidget({x:0, y:0, width:4, height:2, title:'Статистика', content:'График'}));

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

Gridstack.js поддерживает события drag-and-drop и изменения размеров, что позволяет виджетам реагировать на действия пользователя.

Примеры основных событий:

  • added — вызывается после добавления нового виджета
  • change — вызывается при изменении размеров или позиции
  • removed — вызывается при удалении виджета
grid.on('added', function(event, items) {
  items.forEach(item => console.log('Добавлен виджет', item));
});

grid.on('change', function(event, items) {
  items.forEach(item => console.log('Изменение позиции или размера', item));
});

Используя эти события, можно сохранять состояние виджетов на сервере или изменять их содержимое динамически.


Динамическое обновление содержимого и состояния

Кастомные виджеты часто требуют обновления контента без пересоздания DOM-элемента. Для этого можно использовать методы el.querySelector и innerHTML:

function updateWidgetContent(widgetEl, newContent) {
  const body = widgetEl.querySelector('.widget-body');
  if (body) body.innerHTML = newContent;
}

// Пример вызова
const widgetEl = document.querySelector('.grid-stack-item');
updateWidgetContent(widgetEl, '<p>Обновленные данные</p>');

Встраивание сторонних библиотек внутри виджетов

Кастомные виджеты могут содержать графики, таблицы и визуализации. Например, интеграция с Chart.js или D3.js не требует специальных адаптаций со стороны Gridstack, достаточно инициализировать библиотеку внутри .widget-body.

const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, {
  type: 'bar',
  data: { labels: ['Янв','Фев'], datasets: [{label: 'Продажи', data: [12,19]}] }
});

Важно учитывать, что при drag-and-drop или resize некоторые библиотеки требуют вызова метода обновления размера:

grid.on('change', function(event, items) {
  items.forEach(item => {
    if(item.el.querySelector('#myChart')) {
      myChart.resize();
    }
  });
});

Кастомные стили и темы виджетов

Каждый виджет может иметь собственный набор CSS-стилей. Gridstack использует стандартный класс .grid-stack-item-content, который можно переопределять:

.grid-stack-item-content {
  background-color: #f0f0f0;
  border: 1px solid #ccc;
  border-radius: 6px;
  overflow: hidden;
}

.widget-header {
  background-color: #007bff;
  color: #fff;
  padding: 5px 10px;
  font-weight: bold;
}

.widget-body {
  padding: 10px;
}

Для разнообразных тем удобно применять CSS-переменные и динамически менять их при генерации виджетов.


Создание виджетов с настраиваемыми опциями

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

function addCustomWidget(grid, options) {
  const widget = document.createElement('div');
  widget.classList.add('grid-stack-item');
  widget.setAttribute('gs-x', options.x);
  widget.setAttribute('gs-y', options.y);
  widget.setAttribute('gs-width', options.width);
  widget.setAttribute('gs-height', options.height);

  widget.innerHTML = `<div class="grid-stack-item-content">
                        <div class="widget-header">${options.title}</div>
                        <div class="widget-body">${options.content}</div>
                      </div>`;

  grid.addWidget(widget);
}

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


Примеры расширенного функционала

  1. Виджет с кнопками управления — добавление кнопок для закрытия, сворачивания или обновления содержимого.
  2. Виджет с интерактивным графиком — при изменении размера сетки график автоматически перерисовывается.
  3. Виджет с динамической загрузкой данных — подключение к API и обновление таблицы внутри .widget-body при изменении состояния сетки.

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