Для интеграции Muuri с Angular сначала необходимо установить библиотеку через npm:
npm install muuri
После установки рекомендуется использовать ES модули, импортируя Muuri непосредственно в компонент, где будет осуществляться работа с сеткой:
import Muuri from 'muuri';
Angular использует ViewChild и AfterViewInit для взаимодействия с DOM, поэтому создание сетки Muuri производится после инициализации представления компонента.
import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import Muuri from 'muuri';
@Component({
selector: 'app-muuri-grid',
templateUrl: './muuri-grid.component.html',
styleUrls: ['./muuri-grid.component.scss']
})
export class MuuriGridComponent implements AfterViewInit {
@ViewChild('gridContainer', { static: true }) gridContainer!: ElementRef;
private grid!: Muuri;
ngAfterViewInit(): void {
this.grid = new Muuri(this.gridContainer.nativeElement, {
dragEnabled: true,
layout: {
rounding: false
}
});
}
}
HTML-шаблон должен содержать контейнер сетки и элементы, которые будут управляться Muuri. Элементы должны быть обёрнуты в общий контейнер:
<div #gridContainer class="grid">
<div class="item" *ngFor="let item of items">
<div class="item-content">{{ item.name }}</div>
</div>
</div>
CSS для сетки и элементов:
.grid {
display: flex;
flex-wrap: wrap;
}
.item {
width: 150px;
margin: 10px;
}
.item-content {
background: #e0e0e0;
padding: 20px;
text-align: center;
border-radius: 8px;
}
Muuri предлагает широкий набор опций, позволяющих управлять поведением сетки:
dragEnabled – включает возможность перетаскивания элементов.
layout – объект с настройками расположения элементов:
fillGaps: true – элементы заполняют пустое
пространство.rounding: true/false – округление координат при
рендеринге.sortData – функция или объект для сортировки элементов.
items – массив DOM-элементов, который можно передать вручную при инициализации.
Пример кастомной сортировки по имени элемента:
this.grid.sort((a, b) => {
const nameA = a.getElement().textContent?.trim() || '';
const nameB = b.getElement().textContent?.trim() || '';
return nameA.localeCompare(nameB);
});
Angular активно использует двустороннее связывание данных, поэтому добавление или удаление элементов требует синхронизации с Muuri. После изменения массива элементов следует вызвать методы:
const newItem = document.createElement('div');
newItem.classList.add('item');
newItem.innerHTML = `<div class="item-content">Новый элемент</div>`;
this.grid.add(newItem);
const item = this.grid.getItems().find(i => i.getElement().textContent?.includes('Новый элемент'));
if (item) {
this.grid.remove(item, { removeElements: true });
}
this.grid.refreshItems().layout();
Muuri поддерживает гибкую систему перетаскивания элементов. В Angular можно подключить drag-события через опции:
this.grid = new Muuri(this.gridContainer.nativeElement, {
dragEnabled: true,
dragSort: function () {
return [this.gridContainer.nativeElement];
},
dragSortInterval: 50,
dragStartPredicate: {
distance: 0,
delay: 0
}
});
Для более сложных сценариев, например перемещения элементов между разными компонентами Angular, можно использовать события dragReleaseEnd и dragReleaseStart, которые возвращают DOM-элемент и данные элемента, что позволяет синхронизировать состояние приложения:
this.grid.on('dragReleaseEnd', (item) => {
item.getElement().style.zIndex = '';
this.grid.layout();
});
Для динамических приложений рекомендуется использовать RxJS для отслеживания изменений массива элементов. Пример:
import { BehaviorSubject } from 'rxjs';
items$ = new BehaviorSubject<Item[]>([]);
this.items$.subscribe(newItems => {
this.grid.refreshItems().layout();
});
Это позволяет автоматически обновлять сетку при изменении данных в сервисе или состоянии компонента.
Muuri поддерживает фильтры через метод filter. Пример фильтрации по категории:
this.grid.filter(item => item.getElement().dataset.category === 'category1');
Можно сочетать фильтры с сортировкой и drag-and-drop, создавая интерактивные интерфейсы с динамическим контентом в Angular.
layout: { rounding: false } предотвращает
лишние перерисовки.При рендеринге на сервере Muuri не работает, так как он зависит от DOM. Следует использовать условную инициализацию только на клиенте:
if (typeof window !== 'undefined') {
this.grid = new Muuri(this.gridContainer.nativeElement);
}
Это предотвращает ошибки при SSR и позволяет безопасно интегрировать сетку Muuri в проекты с Angular Universal.