Gridstack.js предоставляет мощный механизм работы с сеткой элементов, включая возможность динамического создания и клонирования виджетов. Клонирование элементов особенно полезно при разработке дашбордов, где одни и те же виджеты необходимо многократно использовать с разными данными или настройками.
В Gridstack клонирование элементов реализуется через сочетание методов DOM и API самой библиотеки. Основная идея состоит в том, чтобы создать точную копию существующего виджета, сохранить его размеры и позицию, а затем добавить его в сетку с возможностью дальнейшего изменения.
Базовый способ клонирования элемента в Gridstack.js — использование
стандартного метода cloneNode. Пример:
let original = document.querySelector('.grid-stack-item');
let clone = original.cloneNode(true); // true — глубокое клонирование
document.querySelector('.grid-stack').appendChild(clone);
Однако простой cloneNode копирует только DOM-структуру,
не учитывая внутренние параметры Gridstack, такие как
gs-x, gs-y, gs-width,
gs-height, а также события, связанные с сеткой. Для
корректного клонирования необходимо дополнительно интегрировать
клонированный элемент в API Gridstack.
Gridstack предоставляет методы для создания новых элементов с указанием позиции и размеров:
const grid = GridStack.init();
let original = document.querySelector('.grid-stack-item');
let node = GridStack.Utils.getNodeData(original); // извлечение параметров
let clone = grid.addWidget({
x: node.x,
y: node.y + 1, // смещение клона вниз
width: node.width,
height: node.height,
content: original.innerHTML
});
Пояснения ключевых моментов:
GridStack.Utils.getNodeData(element) — возвращает
объект с параметрами сетки: координаты, размеры, id.grid.addWidget(config) — добавляет новый элемент в
сетку с указанными параметрами.content: original.innerHTML — позволяет сохранить
визуальное содержимое исходного виджета.y предотвращает наложение клона на
оригинальный элемент.Если виджет содержит интерактивные элементы, например кнопки или
формы, простое копирование innerHTML не сохранит
привязанные события. Для этого необходимо использовать
делегирование событий или повторную инициализацию функционала на
клоне:
let cloneNode = original.cloneNode(true);
document.querySelector('.grid-stack').appendChild(cloneNode);
// Повторная инициализация событий
cloneNode.querySelectorAll('button').forEach(btn => {
btn.addEventListener('click', () => console.log('Кнопка в клоне нажата'));
});
Для сложных виджетов рекомендуется хранить данные состояния в объекте и при клонировании передавать их в новый экземпляр:
let state = original.dataset.state; // сохранение состояния
let clone = grid.addWidget({
x: node.x,
y: node.y + 1,
width: node.width,
height: node.height,
content: original.innerHTML
});
clone.dataset.state = state; // восстановление состояния
Gridstack позволяет клонировать сразу несколько элементов, используя массивы:
let items = document.querySelectorAll('.grid-stack-item');
items.forEach((item, index) => {
let node = GridStack.Utils.getNodeData(item);
grid.addWidget({
x: node.x + 2,
y: node.y + 2 * (index + 1),
width: node.width,
height: node.height,
content: item.innerHTML
});
});
Таким образом можно создавать сетки с повторяющимися виджетами, сохраняя их размеры и взаимное расположение, что упрощает построение комплексных интерфейсов.
Еще один эффективный подход — использование шаблонов
template или script[type="text/template"].
Исходный элемент сохраняется как шаблон, а при клонировании создается
его экземпляр:
<template id="widget-template">
<div class="grid-stack-item">
<div class="grid-stack-item-content">Новый виджет</div>
</div>
</template>
let template = document.getElementById('widget-template').content.cloneNode(true);
grid.addWidget({
x: 0,
y: 0,
width: 4,
height: 2,
content: template.querySelector('.grid-stack-item-content').outerHTML
});
Преимущество такого подхода — чистая и управляемая структура виджетов, возможность легкого обновления шаблона и масштабного клонирования без повторной настройки стилей и событий.
При добавлении клона важно учитывать:
x или y, чтобы избежать наложения.grid.addWidget({
x: node.x,
y: node.y + 1,
width: node.width,
height: node.height,
minWidth: node.minWidth,
minHeight: node.minHeight,
maxWidth: node.maxWidth,
maxHeight: node.maxHeight,
content: original.innerHTML
});
GridStack.Utils.getNodeData для точного
извлечения параметров исходного виджета.innerHTML или
шаблоны.Эти практики позволяют создавать динамические, масштабируемые дашборды с повторяющимися виджетами, полностью интегрированными в Gridstack.js, без потери функциональности и внешнего вида.