Gridstack.js предоставляет механизм интеграции элементов, которые изначально не принадлежат сетке. Такие элементы могут находиться в боковой панели, списке компонентов интерфейса или в другой области страницы и добавляться в сетку посредством перетаскивания. Подобная архитектура используется в конструкторах дашбордов, системах визуального проектирования интерфейсов и редакторах макетов.
Интеграция реализуется через стандартный механизм drag-and-drop, встроенный в Gridstack. Внешние элементы становятся источником перетаскивания, а сама сетка — зоной назначения.
Основные сценарии интеграции:
Для того чтобы внешний элемент мог быть перетащен в Gridstack, ему необходимо назначить соответствующий CSS-класс и атрибуты конфигурации.
Простейший пример панели элементов:
<div class="sidebar">
<div class="grid-stack-item">
<div class="grid-stack-item-content">
Новый виджет
</div>
</div>
</div>
<div class="grid-stack"></div>
В этом случае элементы панели уже используют структуру
grid-stack-item, что позволяет Gridstack автоматически
распознавать их параметры.
Однако чаще используется специальный класс:
<div class="sidebar">
<div class="widget-template">
<div class="widget-content">График</div>
</div>
<div class="widget-template">
<div class="widget-content">Таблица</div>
</div>
</div>
Каждый элемент панели является шаблоном будущего виджета.
Для интеграции внешних элементов необходимо активировать режим
acceptWidgets.
const grid = GridStack.init({
acceptWidgets: true
});
Параметр acceptWidgets сообщает библиотеке, что сетка
готова принимать внешние элементы.
Поддерживаются несколько вариантов значения:
| Значение | Описание |
|---|---|
true |
принимать любые элементы |
| CSS-селектор | принимать только указанные элементы |
| функция | кастомная логика проверки |
Пример ограничения по селектору:
GridStack.init({
acceptWidgets: '.widget-template'
});
В этом случае сетка будет принимать только элементы с классом
widget-template.
Gridstack предоставляет утилиту GridStack.setupDragIn,
которая делает внешние элементы перетаскиваемыми.
GridStack.setupDragIn('.widget-template', {
helper: 'clone'
});
Параметры метода:
| Параметр | Назначение |
|---|---|
selector |
CSS-селектор внешних элементов |
options |
настройки drag-поведения |
Опция helper: 'clone' означает, что в сетку будет
добавляться копия элемента, а оригинал останется в панели.
Это стандартная схема для конструкторов интерфейсов.
HTML:
<div class="sidebar">
<div class="widget-template">
Виджет
</div>
</div>
<div class="grid-stack"></div>
Jav * aScript:
const grid = GridStack.init({
acceptWidgets: '.widget-template'
});
GridStack.setupDragIn('.widget-template', {
helper: 'clone'
});
После этого элемент из панели можно перетащить в сетку, где он
автоматически станет grid-stack-item.
Размер и позиция создаваемого элемента могут задаваться через специальные data-атрибуты.
<div class="widget-template"
gs-w="3"
gs-h="2">
График
</div>
Атрибуты:
| Атрибут | Назначение |
|---|---|
gs-w |
ширина |
gs-h |
высота |
gs-x |
позиция по X |
gs-y |
позиция по Y |
Если координаты не указаны, Gridstack автоматически разместит элемент в первой доступной позиции.
При необходимости можно полностью контролировать процесс добавления элемента.
Gridstack генерирует событие dropped.
grid.on('dropped', function(event, previousWidget, newWidget) {
console.log(newWidget);
});
Аргументы:
| Параметр | Описание |
|---|---|
previousWidget |
исходный DOM-элемент |
newWidget |
добавленный элемент сетки |
Этот механизм используется для:
Пример динамической инициализации:
grid.on('dropped', function(event, prev, widget) {
widget.querySelector('.grid-stack-item-content').innerHTML =
'<canvas class="chart"></canvas>';
initChart(widget);
});
Иногда внешний элемент используется только как триггер, а настоящий виджет создаётся программно.
grid.on('dropped', function(event, prev) {
const node = {
w: 4,
h: 3,
content: '<div class="chart-widget"></div>'
};
grid.addWidget(node);
});
В этом случае исходный элемент может быть удалён:
prev.remove();
Подобный подход используется в редакторах дашбордов, где панель содержит лишь типы компонентов.
Шаблоны часто содержат информацию о типе создаваемого виджета.
<div class="widget-template"
data-type="chart">
График
</div>
<div class="widget-template"
data-type="table">
Таблица
</div>
Получение данных:
grid.on('dropped', function(event, prev, widget) {
const type = prev.dataset.type;
if (type === 'chart') {
createChart(widget);
}
if (type === 'table') {
createTable(widget);
}
});
Таким образом панель становится источником конфигурации для создаваемых элементов.
Gridstack позволяет использовать несколько источников элементов.
GridStack.setupDragIn('.charts-panel .widget', {
helper: 'clone'
});
GridStack.setupDragIn('.tables-panel .widget', {
helper: 'clone'
});
Сетка принимает все элементы, если они удовлетворяют параметру
acceptWidgets.
Gridstack поддерживает перенос элементов между разными сетками.
HTML:
<div class="grid-stack grid-1"></div>
<div class="grid-stack grid-2"></div>
Jav * aScript:
GridStack.init({
acceptWidgets: true
}, '.grid-1');
GridStack.init({
acceptWidgets: true
}, '.grid-2');
Теперь элементы можно перемещать между сетками.
Это используется в:
Сетка может фильтровать допустимые виджеты.
GridStack.init({
acceptWidgets: function(el) {
return el.dataset.type !== 'restricted';
}
});
Функция возвращает true или false.
Подобная логика применяется, когда:
Во время перетаскивания используется специальный элемент-превью.
GridStack.setupDragIn('.widget-template', {
helper: function(el) {
const clone = el.cloneNode(true);
clone.style.width = '200px';
return clone;
}
});
Кастомный helper позволяет:
В реальных проектах панель компонентов обычно представляет собой полноценный UI-модуль.
Типичная структура:
sidebar
├── charts
├── tables
├── widgets
└── media
Каждая группа содержит собственные шаблоны.
Gridstack подключается только к тем элементам, которые должны быть перетаскиваемыми.
GridStack.setupDragIn('.sidebar .widget');
Во время drag-операции Gridstack показывает временный placeholder.
Его внешний вид можно изменить через CSS.
.grid-stack-placeholder {
background: rgba(0,0,0,0.1);
border: 2px dashed #666;
}
Placeholder помогает пользователю визуально понимать, где будет размещён элемент.
После добавления виджета может выполняться запрос к серверу.
grid.on('dropped', async function(event, prev, widget) {
const data = await fetch('/widget-data').then(r => r.json());
renderWidget(widget, data);
});
Это позволяет:
Часто структура виджета хранится в <template>.
<template id="chart-template">
<div class="grid-stack-item-content">
<canvas class="chart"></canvas>
</div>
</template>
При drop-событии:
grid.on('dropped', function(event, prev, widget) {
const template = document.getElementById('chart-template');
widget.innerHTML = template.innerHTML;
});
Этот подход упрощает поддержку сложных интерфейсов.
Интеграция внешних элементов обычно строится по следующей схеме:
dropped создаёт полноценный виджетТакой подход обеспечивает:
Gridstack выступает только механизмом компоновки, тогда как логика виджетов полностью контролируется приложением.