Gridstack.js предоставляет мощный механизм для построения интерактивных сеток с поддержкой drag-and-drop и динамического изменения размеров элементов. Для расширенной функциональности часто требуется создавать кастомные виджеты, которые обладают уникальной разметкой, стилями и поведением.
Кастомный виджет в Gridstack.js — это не просто HTML-элемент, помещённый в сетку, а объект, который может управлять своим состоянием, взаимодействовать с событиями сетки и динамически изменять размеры или позицию.
Ключевыми элементами любого виджета являются:
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>
Содержимое виджета Внутри элемента
.grid-stack-item-content размещается вся визуальная часть.
Здесь можно добавлять кнопки, графики, таблицы или другие интерактивные
элементы.
Метаданные виджета Для хранения состояния и
конфигурации виджета удобно использовать data- атрибуты или
объекты в JS, например:
const widgetData = {
id: 'widget1',
type: 'chart',
options: { color: 'blue', title: 'Продажи' }
};
После создания 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);
}
Это позволяет легко создавать повторяемые виджеты с разной конфигурацией, минимизируя дублирование кода.
.widget-body
при изменении состояния сетки.Gridstack.js предоставляет все инструменты для комбинирования визуальных компонентов и интерактивности, делая кастомные виджеты гибкими и управляемыми.