Angular

SortableJS — это современная библиотека для создания интерактивных списков с возможностью перетаскивания элементов. Для интеграции в Angular-проект рекомендуется использовать официальный пакет sortablejs и обертку ngx-sortablejs, которая упрощает работу с Angular-компонентами и реактивными формами.

Установка через npm:

npm install sortablejs ngx-sortablejs --save

Импорт модуля в Angular:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { SortablejsModule } from 'ngx-sortablejs';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    SortablejsModule.forRoot({ animation: 150 }) // глобальные настройки
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Основная структура и использование

SortableJS работает с HTML-элементами списка (ul, ol, div). Для Angular-компонентов можно привязать данные с помощью *ngFor.

Пример базовой реализации:

<ul [sortablejs]="items" [sortablejsOptions]="sortableOptions">
  <li *ngFor="let item of items">{{ item.name }}</li>
</ul>
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  items = [
    { name: 'Элемент 1' },
    { name: 'Элемент 2' },
    { name: 'Элемент 3' },
  ];

  sortableOptions = {
    animation: 200,
    onEnd: (event: any) => {
      console.log('Элемент перемещён', event);
    }
  };
}

Ключевые моменты:

  • [sortablejs] — привязка массива данных к списку.
  • [sortablejsOptions] — объект с настройками поведения.
  • onEnd — событие, вызываемое после завершения перетаскивания.

Настройки и конфигурация

SortableJS предоставляет множество параметров для гибкой настройки:

  • animation — скорость анимации перемещения (в миллисекундах).
  • group — позволяет объединять списки для перетаскивания между ними.
  • handle — CSS-селектор элемента, который можно перетаскивать.
  • draggable — CSS-селектор элементов, которые можно перетаскивать.
  • filter — селектор для исключения элементов из перетаскивания.
  • sort — логическое значение, разрешающее сортировку внутри списка.
  • disabled — включение/отключение перетаскивания динамически.

Пример с групповым перетаскиванием:

<div class="list-container">
  <ul [sortablejs]="listA" [sortablejsOptions]="{ group: 'shared' }">
    <li *ngFor="let item of listA">{{ item }}</li>
  </ul>

  <ul [sortablejs]="listB" [sortablejsOptions]="{ group: 'shared' }">
    <li *ngFor="let item of listB">{{ item }}</li>
  </ul>
</div>
listA = ['A1', 'A2', 'A3'];
listB = ['B1', 'B2', 'B3'];

Элементы можно перетаскивать между списками благодаря одинаковому значению group.


События

SortableJS предоставляет множество событий, позволяющих реагировать на действия пользователя:

  • onStart — начало перетаскивания.
  • onEnd — завершение перетаскивания.
  • onAdd — элемент добавлен в список.
  • onUpdate — элемент изменил позицию внутри списка.
  • onRemove — элемент удалён из списка.
  • onSort — любой сдвиг элемента внутри списка.
  • onFilter — сработало исключение фильтра.

Пример обработки события onAdd:

sortableOptions = {
  group: 'shared',
  onAdd: (event: any) => {
    console.log('Добавлен элемент:', event.item.textContent);
  }
};

Работа с динамическими данными

SortableJS в Angular легко интегрируется с реактивными формами и сервисами. Массивы, привязанные через [sortablejs], автоматически обновляются при перемещении элементов, что исключает необходимость ручной синхронизации DOM и данных.

Для обновления списка можно использовать стандартные методы массивов:

onEnd(event: any) {
  const movedItem = this.items.splice(event.oldIndex, 1)[0];
  this.items.splice(event.newIndex, 0, movedItem);
}

Стилизация и кастомизация

SortableJS позволяет полностью контролировать внешний вид:

  • Стили для перетаскиваемого элемента (.sortable-chosen).
  • Стили для места назначения (.sortable-ghost).
  • Возможность использования кастомных классов через setClassName.

Пример CSS:

ul li {
  padding: 10px;
  margin: 5px 0;
  background: #f2f2f2;
  border: 1px solid #ccc;
  cursor: grab;
}

ul li.sortable-chosen {
  background: #d1e7fd;
}

ul li.sortable-ghost {
  opacity: 0.5;
}

Дополнительные возможности

  • Поддержка вложенных списков — с помощью nestedSortable.
  • Поддержка мобильных устройств — работает с touch-событиями.
  • Перетаскивание между таблицами и контейнерами — позволяет строить сложные интерфейсы с drag-and-drop.
  • Интеграция с Angular CDK — можно комбинировать функциональность DragDropModule и SortableJS для расширенных сценариев.

Оптимизация и производительность

  • Минимизировать количество DOM-элементов при больших списках.
  • Использовать trackBy в *ngFor для предотвращения перерисовки всех элементов.
  • Настраивать анимацию через animation для плавного UX без перегрузки рендеринга.
<li *ngFor="let item of items; trackBy: trackByFn">{{ item.name }}</li>
trackByFn(index: number, item: any) {
  return item.id;
}

Использование trackBy позволяет Angular эффективно обновлять только перемещённые элементы, сохраняя производительность при сотнях элементов.