Top Related Projects
Reorderable drag-and-drop lists for modern browsers and touch devices. No jQuery or framework required.
:ok_hand: Drag and drop so simple it hurts
VanillaJS sortable lists and grids using native HTML5 drag and drop API.
The JavaScript Drag & Drop library your grandparents warned you about.
Beautiful and accessible drag and drop for lists with React
Quick Overview
Angular UI Sortable is a directive for AngularJS that integrates jQuery UI's sortable functionality into Angular applications. It allows users to create sortable lists with drag-and-drop capabilities, enhancing the user interface and interaction of web applications.
Pros
- Easy integration with AngularJS projects
- Leverages the power of jQuery UI sortable
- Supports two-way data binding
- Customizable with various options and callbacks
Cons
- Depends on jQuery and jQuery UI, which may increase the overall bundle size
- Limited to AngularJS, not compatible with newer Angular versions (2+)
- May require additional configuration for complex sorting scenarios
- Performance can be affected when dealing with large lists
Code Examples
- Basic usage:
<ul ui-sortable ng-model="items">
<li ng-repeat="item in items">{{ item }}</li>
</ul>
This example creates a simple sortable list using the ui-sortable
directive and ng-model
for two-way data binding.
- Customizing options:
$scope.sortableOptions = {
handle: '.handle',
axis: 'y',
stop: function(e, ui) {
// Do something after sorting
}
};
<ul ui-sortable="sortableOptions" ng-model="items">
<li ng-repeat="item in items">
<span class="handle">☰</span> {{ item }}
</li>
</ul>
This example demonstrates how to customize the sortable behavior by specifying options such as a handle for dragging and restricting movement to the y-axis.
- Connected lists:
<ul ui-sortable="sortableOptions" ng-model="list1">
<li ng-repeat="item in list1">{{ item }}</li>
</ul>
<ul ui-sortable="sortableOptions" ng-model="list2">
<li ng-repeat="item in list2">{{ item }}</li>
</ul>
$scope.sortableOptions = {
connectWith: '.connected-sortable-list'
};
This example shows how to create connected sortable lists, allowing items to be dragged between them.
Getting Started
-
Install the package:
npm install angular-ui-sortable
-
Include the necessary dependencies in your HTML:
<script src="path/to/angular.js"></script> <script src="path/to/jquery.js"></script> <script src="path/to/jquery-ui.js"></script> <script src="path/to/sortable.js"></script>
-
Add the module to your Angular app:
angular.module('myApp', ['ui.sortable']);
-
Use the
ui-sortable
directive in your HTML:<ul ui-sortable ng-model="items"> <li ng-repeat="item in items">{{ item }}</li> </ul>
-
Define the
items
array in your controller:$scope.items = ['Item 1', 'Item 2', 'Item 3'];
Competitor Comparisons
Reorderable drag-and-drop lists for modern browsers and touch devices. No jQuery or framework required.
Pros of Sortable
- Framework-agnostic, works with vanilla JavaScript and various frameworks
- More feature-rich, including multi-drag, swap, and animation options
- Actively maintained with frequent updates and improvements
Cons of Sortable
- Steeper learning curve for complex implementations
- Larger file size due to additional features
Code Comparison
ui-sortable:
$scope.sortableOptions = {
update: function(e, ui) {
// Handle update event
}
};
Sortable:
new Sortable(el, {
onUpdate: function (evt) {
// Handle update event
}
});
Key Differences
- ui-sortable is specifically designed for AngularJS, while Sortable is framework-agnostic
- Sortable offers more advanced features and customization options
- ui-sortable relies on jQuery UI, whereas Sortable is a standalone library
Use Cases
- Choose ui-sortable for AngularJS projects with simple sorting needs
- Opt for Sortable for more complex sorting requirements or when working with multiple frameworks
Community and Support
- ui-sortable has a smaller, AngularJS-focused community
- Sortable boasts a larger, diverse community across various frameworks
Performance
- Sortable generally offers better performance, especially for larger lists
- ui-sortable may have slight overhead due to AngularJS bindings
:ok_hand: Drag and drop so simple it hurts
Pros of Dragula
- Framework-agnostic, works with any JavaScript project
- Simpler API and easier to set up
- Supports touch events for mobile devices
Cons of Dragula
- Less customization options for advanced use cases
- Doesn't provide built-in Angular directives
Code Comparison
ui-sortable:
$scope.sortableOptions = {
update: function(e, ui) {
// Handle update event
},
axis: 'y',
containment: 'parent'
};
Dragula:
dragula([document.querySelector('#left-container'), document.querySelector('#right-container')], {
moves: function (el, source, handle, sibling) {
return true; // elements are always draggable by default
}
});
Summary
ui-sortable is specifically designed for AngularJS applications and provides deep integration with Angular's digest cycle. It offers more advanced configuration options and is better suited for complex sorting scenarios within Angular projects.
Dragula, on the other hand, is a lightweight and flexible drag-and-drop library that can be used with any JavaScript framework or vanilla JS. It has a simpler API and is easier to set up, making it a good choice for projects that don't require extensive customization or Angular-specific features.
The choice between the two depends on the project requirements, framework preferences, and the level of customization needed for drag-and-drop functionality.
VanillaJS sortable lists and grids using native HTML5 drag and drop API.
Pros of html5sortable
- Lightweight and framework-agnostic, making it more versatile for different projects
- Native HTML5 drag and drop API, potentially better performance
- Simpler setup without Angular dependencies
Cons of html5sortable
- Less integrated with Angular ecosystem
- May require more manual configuration for complex use cases
- Potentially fewer built-in features compared to ui-sortable
Code Comparison
ui-sortable (Angular.js):
angular.module('myApp', ['ui.sortable'])
.controller('MyCtrl', function($scope) {
$scope.items = ['Item 1', 'Item 2', 'Item 3'];
$scope.sortableOptions = { /* options */ };
});
html5sortable:
import sortable from 'html5sortable';
sortable('.sortable-list', {
// options
});
Key Differences
- ui-sortable is specifically designed for Angular.js applications, while html5sortable is framework-agnostic
- html5sortable uses native HTML5 drag and drop, potentially offering better performance
- ui-sortable integrates more seamlessly with Angular's data binding and digest cycle
- html5sortable may require additional work to integrate with complex Angular applications
- ui-sortable offers more built-in features and options out of the box
Both libraries have their strengths, and the choice between them depends on the specific project requirements, framework preferences, and desired level of integration with Angular.
The JavaScript Drag & Drop library your grandparents warned you about.
Pros of Draggable
- Framework-agnostic, can be used with any JavaScript project
- More extensive features, including multiple drag and drop libraries for different use cases
- Active development and maintenance, with regular updates and improvements
Cons of Draggable
- Steeper learning curve due to more complex API and configuration options
- Larger file size, which may impact performance for smaller projects
- Requires more setup and configuration compared to ui-sortable
Code Comparison
ui-sortable:
<ul ui-sortable ng-model="items">
<li ng-repeat="item in items">{{ item }}</li>
</ul>
Draggable:
import { Sortable } from '@shopify/draggable';
const sortable = new Sortable(document.querySelectorAll('ul'), {
draggable: 'li'
});
Summary
Draggable offers more flexibility and features but requires more setup, while ui-sortable provides a simpler integration for Angular projects. Draggable is better suited for complex drag and drop requirements across various frameworks, whereas ui-sortable is ideal for quick implementation in Angular applications with basic sorting needs.
Beautiful and accessible drag and drop for lists with React
Pros of react-beautiful-dnd
- Built specifically for React, offering seamless integration and better performance
- Provides a more accessible drag and drop experience with keyboard support
- Offers advanced features like multi-drag and combining items
Cons of react-beautiful-dnd
- Limited to vertical lists and horizontal lists, lacking support for grid layouts
- Steeper learning curve due to its more complex API and concepts
Code Comparison
ui-sortable:
$scope.sortableOptions = {
update: function(e, ui) {
// Handle update event
},
axis: 'y'
};
react-beautiful-dnd:
<DragDropContext onDragEnd={this.onDragEnd}>
<Droppable droppableId="list">
{(provided) => (
<div {...provided.droppableProps} ref={provided.innerRef}>
{/* Draggable items */}
</div>
)}
</Droppable>
</DragDropContext>
Key Differences
- ui-sortable is designed for AngularJS, while react-beautiful-dnd is tailored for React applications
- react-beautiful-dnd offers a more declarative API, whereas ui-sortable relies on configuration objects
- ui-sortable provides more flexibility in terms of layout options, including grid support
- react-beautiful-dnd focuses on accessibility and advanced drag and drop features, making it more suitable for complex use cases
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
UI.Sortable directive
This directive allows you to sort an array with drag & drop.
Requirements
- JQuery v3.1+ (for jQuery v1.x & v2.x use v0.14.x versions)
- JQueryUI v1.12+
- AngularJS v1.2+
Single minified cdn link ~245kB and example with JQuery v1.x, required parts of JQueryUI v1.10, AngularJS v1.2 & latest angular-ui-sortable.
Notes:
- JQuery must be included before AngularJS.
- JQueryUI dependecies include widget, data, scroll-parent, mouse & sortable. Creating a custom build will greatly reduce the required file size. (CDN links for comparison: full vs minimal)
- Users of AngularJS pre v1.2 can use v0.10.x or v0.12.x branches.
- Early adopters of Angular2 can use the ng2 branch.
Installation
- Install with Bower
bower install -S angular-ui-sortable
- Install with npm
npm install -S angular-ui-sortable
- Download one of the Releases or the latest Master branch
Usage
Load the script file: sortable.js in your application:
<script type="text/javascript" src="modules/directives/sortable/src/sortable.js"></script>
Add the sortable module as a dependency to your application module:
var myAppModule = angular.module('MyApp', ['ui.sortable'])
Apply the directive to your form elements:
<ul ui-sortable ng-model="items">
<li ng-repeat="item in items">{{ item }}</li>
</ul>
Developing Notes:
ng-model
is required, so that the directive knows which model to update.ui-sortable
element should contain only oneng-repeat
, but other non-repeater elements above or below may still exist. Otherwise the index matching of theng-model
's items and the DOM elements generated by theng-repeat
will break.
In other words: The items ofng-model
must match the indexes of the DOM elements generated by theng-repeat
.Filters
that manipulate the model (like filter, orderBy, limitTo,...) should be applied in thecontroller
instead of theng-repeat
(refer to the provided examples).
This is the preferred way since it:- is performance wise better
- reduces the chance of code duplication
- is suggested by the angularJS team
- it does not break the matching of the generated DOM elements and the
ng-model
's items
ui-sortable
lists containing many 'types' of items can be implemented by using dynamic template loading with ng-include or a loader directive, to determine how each model item should be rendered. Also take a look at the Tree with dynamic template example.
Options
All the jQueryUI Sortable options can be passed through the directive.
Additionally, the ui
argument of the available callbacks gets enriched with some extra properties as specified to the API.md file.
Any model changes that happen inside the available callbacks, are applied right after the stop event. We are not wrapping callbacks like start
/change
/... with $apply
, in order to minimize the number of digest loops and avoid possible modifications of the model (eg: by watchers) before the drop takes place.
myAppModule.controller('MyController', function($scope) {
$scope.items = ["One", "Two", "Three"];
$scope.sortableOptions = {
update: function(e, ui) { ... },
axis: 'x'
};
});
<ul ui-sortable="sortableOptions" ng-model="items">
<li ng-repeat="item in items">{{ item }}</li>
</ul>
When using event callbacks (start/update/stop...), avoid manipulating DOM elements (especially the one with the ng-repeat attached). The suggested pattern is to use callbacks for emmiting events and altering the scope (inside the 'Angular world').
ui-floating
ui-floating (default: undefined)
Description: Enables a workaround for smooth horizontal sorting.
Type: Boolean/String/undefined
- undefined: Relies on jquery.ui to detect the list's orientation.
- false: Forces jquery.ui.sortable to detect the list as vertical.
- true: Forces jquery.ui.sortable to detect the list as horizontal.
- "auto": Detects on each drag
start
if the element is floating or not.
To have a smooth horizontal-list reordering, jquery.ui.sortable needs to detect the orientation of the list. This detection takes place during the initialization of the plugin (and some of the checks include: whether the first item is floating left/right or if 'axis' parameter is 'x', etc). There is also a known issue about initially empty horizontal lists.
To provide a solution/workaround (till jquery.ui.sortable.refresh() also tests the orientation or a more appropriate method is provided), ui-sortable directive provides a ui-floating
option as an extra to the jquery.ui.sortable options.
<ul ui-sortable="{ 'ui-floating': true }" ng-model="items">
<li ng-repeat="item in items">{{ item }}</li>
</ul>
OR
$scope.sortableOptions = {
'ui-floating': true
};
<ul ui-sortable="sortableOptions" ng-model="items">
<li ng-repeat="item in items">{{ item }}</li>
</ul>
ui-model-items
ui-model-items (default: > [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]
)
Description: Defines which elements should be considered as part of your model.
Type: CSS selector/String
This is the model related counterpart option of jQuery's items option.
ui-preserve-size
ui-preserve-size (default: undefined)
Description: Set's the size of the sorting helper to the size of the original element before the sorting.
Type: Boolean/undefined
This is useful for elements that their size is dependent to other page characteristics.
A representative example of such cases are <table>
<tr>
s and <td>
s.
Attributes For Event Handling
To handle events with html bindings just define any expression to listed event attributes. If you defined an attribute for this events and defined callback function in sortableOptions at the same time, the attribute based callback will be called first.
- ui-sortable-start
- ui-sortable-activate
- ui-sortable-before-stop
- ui-sortable-update
- ui-sortable-remove
- ui-sortable-receive
- ui-sortable-deactivate
- ui-sortable-stop
Expression works on update event.
<ul ui-sortable ng-model="items" ui-sortable-update="expression" >
<li ng-repeat="item in items">{{ item }}</li>
</ul>
On update event callBackFunction1 if called before callBackFunction2.
$scope.sortableOptions = {
'update': callBackFunction2
};
<ul ui-sortable="sortableOptions" ng-model="items" ui-sortable-update="callBackFunction1" >
<li ng-repeat="item in items">{{ item }}</li>
</ul>
Canceling
Inside the update
callback, you can check the item that is dragged and cancel the sorting.
$scope.sortableOptions = {
update: function(e, ui) {
if (ui.item.sortable.model == "can't be moved") {
ui.item.sortable.cancel();
}
}
};
Notes:
update
is the appropriate place to cancel a sorting, since it occurs before any model/scope changes but after the DOM position has been updated. Soui.item.scope
and the directive'sng-model
, are equal to the scope before the drag start.- To cancel a sorting between connected lists,
cancel
should be called inside theupdate
callback of the originating list. A simple way to is to use theui.item.sortable.received
property:
update: function(event, ui) {
if (// ensure we are in the first update() callback
!ui.item.sortable.received &&
// check that its an actual moving between the two lists
ui.item.sortable.source[0] !== ui.item.sortable.droptarget[0] &&
// check the size limitation
ui.item.sortable.model == "can't be moved between lists") {
ui.item.sortable.cancel();
}
}
jQueryUI Sortable Event order
Single sortable demo
create
/* dragging starts */
helper
start
activate
/* multiple: sort/change/over/out */
beforeStop
update <= call cancel() here if needed
deactivate
stop
Connected sortables demo
list A: create
list B: create
/* dragging starts from sortable A to B */
list A: helper
list A: start
list B: activate
list A: activate
/* both lists multiple: sort/change/over/out */
list A: sort
list A: change
list B: change
list B: over
list A: sort
list B: out
list A: sort
list A: beforeStop
list A: update <= call cancel() here if needed
list A: remove
list B: receive
list B: update
list B: deactivate
list A: deactivate
list A: stop
For more details about the events check the jQueryUI API documentation.
Integrating with directives doing transclusion
Wrap the transclusion directive element with the ui-sortable directive and set the items
to target your ng-repeat
ed elements. Following best practices, it is also highly recommended that you add a track by
expression to your ng-repeat
. Angular Material example.
myAppModule.controller('MyController', function($scope) {
$scope.items = ["One", "Two", "Three"];
$scope.sortableOptions = {
items: '.sortable-item'
// It is suggested to use the most specific cssselector you can,
// after analyzing the DOM elements generated by the transclusion directive
// eg: items: '> .transclusionLvl1 > .transclusionLvl2 > .sortable-item'
};
});
<div ui-sortable="sortableOptions" ng-model="items">
<a-transclusion-directive>
<div ng-repeat="item in items" class="sortable-item">{{ item }}</div>
</a-transclusion-directive>
</div>
Examples
- Simple Demo
- Connected Lists
- Filtering (details)
- Ordering 1 & Ordering 2 (details)
- Cloning (details)
- Horizontal List
- Tree with dynamic template
- Canceling
- Locked Items
- Draggable Handle
- Drop Zone
- Draggable-Sortable like interaction
- Static HTML Sorting
Integrations
- firebase
- ui.bootstrap.accordion
- Angular Material (thanks yenoh2)
- Asynchronous loading jQuery+jQueryUI with crisbeto/angular-ui-sortable-loader
Reporting Issues
The above pen's are provided as a good starting point to demonstrate issues, proposals and use cases. Feel free to edit any of them for your needs (don't forget to also update the libraries used to your version).
Testing
We use Karma and JSHint to ensure the quality of the code. The easiest way to run these checks is to use grunt:
npm install -g grunt-cli
npm install && bower install
grunt
The karma task will try to open Firefox and Chrome as browser in which to run the tests. Make sure this is available or change the configuration in test\karma.conf.js
.
Grunt Serve
We have one task to serve them all!
grunt serve
It's equal to run separately:
-
grunt connect:server
: giving you a development server at http://127.0.0.1:8000/. -
grunt karma:server
: giving you a Karma server to run tests (at http://localhost:9876/ by default). You can force a test on this server withgrunt karma:unit:run
. -
grunt watch
: will automatically test your code and build your demo. You can demo generation withgrunt build:gh-pages
.
Top Related Projects
Reorderable drag-and-drop lists for modern browsers and touch devices. No jQuery or framework required.
:ok_hand: Drag and drop so simple it hurts
VanillaJS sortable lists and grids using native HTML5 drag and drop API.
The JavaScript Drag & Drop library your grandparents warned you about.
Beautiful and accessible drag and drop for lists with React
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot