ng-hub-ui-sortable

ng-hub-ui-sortable provides a complete, modern integration of SortableJS for Angular, letting you build interactive UIs with drag-and-drop functionality in a simple, declarative way.

The library covers simple scenarios like reordering items in a list, as well as advanced cases such as nested lists, item transfer between multiple lists, item cloning, integration with Angular Reactive Forms (FormArray) and Angular Signals (WritableSignal), and full customization via options and events. Every drag-and-drop action syncs automatically with your data model, keeping your app reactive and predictable.

Features

  • Simple directive to make any container sortable
  • Syncs drag-and-drop with arrays, FormArray, and writable signals
  • Native support for Angular signals for reactive state management
  • Access to the full SortableJS API and events within Angular zone
  • Multi-list support, cloning, and custom clone functions
  • Individual inputs for all SortableJS options
  • Full TypeScript with strong typing

Installation

npm install ng-hub-ui-sortable sortablejs
npm install -D @types/sortablejs

Peer dependencies: Angular >= 18 and SortableJS >= 1.7.0.

You can also use yarn add ng-hub-ui-sortable sortablejs.

Quick start

Import the module with global options:

import { SortableModule } from 'ng-hub-ui-sortable';

@NgModule({
  imports: [SortableModule.forRoot({ animation: 150 })]
})
export class AppModule {}

Create a component with your array:

items = ['Item 1', 'Item 2', 'Item 3'];

And use it in the template:

<div [hubSortable]="items" [animation]="150">
  @for (item of items; track item) {
    <div class="p-2 border">&#123;&#123; item &#125;&#125;</div>
  }
</div>

Full directive API

Main inputs

InputTypeDescription
[hubSortable]any[] | FormArray | WritableSignal<any[]>Array, FormArray, or writable signal synchronized with drag-and-drop
[container]stringCSS selector of the actual container (optional)
[options]OptionsSortableJS options object
[cloneFunction](item: any) => anyCustom function to clone items

Individual option inputs

All SortableJS options can be provided as individual inputs:

  • [group] - Group name for multi-list
  • [sort] - Enable/disable sorting
  • [delay] - Delay before starting drag (ms)
  • [disabled] - Disable the sortable
  • [draggable] - CSS selector for draggable items
  • [handle] - CSS selector for the drag handle
  • [animation] - Animation speed (ms)
  • [ghostClass] - CSS class for the ghost element
  • [chosenClass] - CSS class for the chosen element
  • [dragClass] - CSS class for the dragging element
  • [filter] - Filter for non-draggable elements
  • [preventOnFilter] - preventDefault on filter
  • [direction] - Direction ('vertical' | 'horizontal')
  • [swapThreshold] - Swap zone threshold
  • [invertSwap] - Invert swap threshold
  • [fallbackOnBody] - Add ghost to body
  • [fallbackTolerance] - Fallback tolerance (px)
  • [fallbackClass] - CSS class for fallback
  • [forceFallback] - Force fallback activation
  • [touchStartThreshold] - Touch start threshold
  • [emptyInsertThreshold] - Empty insert threshold
  • [delayOnTouchOnly] - Delay on touch only
  • [easing] - Easing function for animation
  • [dataIdAttr] - HTML attribute for data id
  • [removeCloneOnHide] - Remove clone on hide
  • And more advanced options...

Outputs (events)

All events run within the Angular zone:

OutputTypeDescription
(init)SortableEmits the Sortable instance on init
(start)SortableEventFires when dragging starts
(end)SortableEventFires when dragging ends
(add)SortableEventItem added from another list
(remove)SortableEventItem removed to another list
(update)SortableEventPosition updated within the same list
(sortEvent)SortableEventList sorted (any change)
(change)SortableEventList changed after adding or removing item
(choose)SortableEventItem chosen (mouse down)
(unchoose)SortableEventItem unchosen (mouse up without drag)
(clone)SortableEventItem cloned in clone mode
(filterEvent)SortableEventAttempt to drag filtered element
(move){ event: MoveEvent; originalEvent: Event }Fires during drag movement

Example with events

// Component
export class MyComponent {
  items = ['Item 1', 'Item 2', 'Item 3'];

  onDragStart(event: SortableEvent) {
    console.log('Drag started:', event);
  }

  onDragEnd(event: SortableEvent) {
    console.log('Drag ended:', event);
  }

  onUpdate(event: SortableEvent) {
    console.log('List updated:', this.items);
  }
}
<!-- Template -->
<div [hubSortable]="items"
     [animation]="200"
     [handle]="'.drag-handle'"
     (start)="onDragStart($event)"
     (end)="onDragEnd($event)"
     (update)="onUpdate($event)">
  @for (item of items; track item) {
    <div class="sortable-item">
      <span class="drag-handle">☰</span>
      &#123;&#123; item &#125;&#125;
    </div>
  }
</div>

Interactive demos

Explore these live demos to see ng-hub-ui-sortable in action. Each example shows different capabilities and common usage patterns:

ng-hub-ui family

Other related components:

Inspiration and credits

This package is a fork of @worktile/ngx-sortablejs, keeping the same API while updating branding and metadata to align with the ng-hub-ui family.

Special thanks to the Worktile team for their great initial work integrating SortableJS with Angular.

Contributions

Contributions are welcome! Here's how you can help:

  1. Fork the repository
  2. Create your feature branch: git checkout -b feature/my-new-feature
  3. Commit your changes: git commit -am 'Add some feature'
  4. Push the branch: git push origin feature/my-new-feature
  5. Open a pull request

If you find any issues, please report them on: GitHub Issues

Support the project

If you find this project useful and want to support its development, you can buy me a coffee:

Buy Me A Coffee

Your support is greatly appreciated and helps maintain and improve this project!

License

This project is licensed under the Creative Commons Attribution 4.0 International (CC BY 4.0).

You may:

  • Use commercially and non-commercially
  • Modify, adapt, and create derivatives
  • Distribute and redistribute in any format
  • Use in private and public projects

You must:

  • Give appropriate credit to the original authors
  • Provide a link to the license
  • Indicate if changes were made
Attribution example:
Based on ng-hub-ui-sortable by Carlos Morcillo
Original: https://github.com/carlos-morcillo/ng-hub-ui-sortable
License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

For more details about the license, see the LICENSE file.