• This repository has been archived on 08/Sep/2020
  • Stars
    star
    1,265
  • Rank 37,188 (Top 0.8 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 11 years ago
  • Updated about 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

jQuery UI Sortable for AngularJS

UI.Sortable directive

npm npm Build Status Coverage Status debugInfoEnabled(false) Ready Badge Join the chat at https://gitter.im/angular-ui/ui-sortable

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:

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 one ng-repeat, but other non-repeater elements above or below may still exist. Otherwise the index matching of the ng-model's items and the DOM elements generated by the ng-repeat will break.
    In other words: The items of ng-model must match the indexes of the DOM elements generated by the ng-repeat.
  • Filters that manipulate the model (like filter, orderBy, limitTo,...) should be applied in the controller instead of the ng-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. So ui.item.scope and the directive's ng-model, are equal to the scope before the drag start.
  • To cancel a sorting between connected lists, cancel should be called inside the update callback of the originating list. A simple way to is to use the ui.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-repeated 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

Integrations

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 with grunt karma:unit:run.

  • grunt watch : will automatically test your code and build your demo. You can demo generation with grunt build:gh-pages.

More Repositories

1

bootstrap

PLEASE READ THE PROJECT STATUS BELOW. Native AngularJS (Angular) directives for Bootstrap. Smaller footprint (20kB gzipped), no 3rd party JS dependencies (jQuery, bootstrap JS) required. Please read the README.md file before submitting an issue!
JavaScript
14,347
star
2

ui-router

The de-facto solution to flexible routing with nested views in AngularJS
TypeScript
13,611
star
3

ui-grid

UI Grid: an Angular Data Grid
JavaScript
5,386
star
4

ui-select

AngularJS-native version of Select2 and Selectize
JavaScript
3,278
star
5

angular-google-maps

AngularJS directives for the Google Maps Javascript API
CoffeeScript
2,530
star
6

angular-ui-OLDREPO

DISCONTINUED REPO: This project has been restructured ->
JavaScript
2,210
star
7

ui-calendar

A complete AngularJS directive for the Arshaw FullCalendar.
JavaScript
1,494
star
8

ui-utils

Deprecated collection of modules for angular
JavaScript
1,443
star
9

AngularJS-sublime-package

AngularJS code completion, snippets, go to definition, quick panel search, and more.
JavaScript
1,422
star
10

ui-select2

AngularJS wrapper for select2 (deprecated, use angular-ui/ui-select)
JavaScript
594
star
11

ui-ace

This directive allows you to add ACE editor elements.
JavaScript
580
star
12

ui-tinymce

AngularUI wrapper for TinyMCE
JavaScript
490
star
13

ui-layout

This directive allows you to split !
JavaScript
410
star
14

ui-mask

Mask on an input field so the user can only type pre-determined pattern
JavaScript
393
star
15

ui-codemirror

This directive allows you to add CodeMirror to your textarea elements.
JavaScript
383
star
16

ui-grid.info

Website for ui-grid
377
star
17

ui-scroll

Unlimited bidirectional scrolling over a limited element buffer for AngularJS applications
JavaScript
324
star
18

ui-leaflet

AngularJS directive to embed an interact with maps managed by Leaflet library
JavaScript
316
star
19

AngularJS-StyleGuide

Example of scalable architecture for my NG-Conf 2014 talk
JavaScript
287
star
20

ui-map

Google Maps
JavaScript
285
star
21

AngularJS-Atom

An AngularJS package for Github's Atom editor
CoffeeScript
285
star
22

ui-date

jQuery UI Datepicker for AngularJS
JavaScript
266
star
23

ui-slider

jQuery UI Slider for AngularJS
HTML
265
star
24

AngularJS-brackets

AngularJS plugin for Brackets (booya)
JavaScript
217
star
25

bootstrap-bower

This is a bower repository to hold Angular UI Bootstrap releases.
JavaScript
158
star
26

alias

Create concise aliases for third-party directives and templates
JavaScript
115
star
27

ui-mention

Facebook-like @mentions for text inputs built around composability
JavaScript
115
star
28

ui-validate

General-purpose validator for ngModel
JavaScript
111
star
29

ui-chart

This directive lets you use jqPlot with Angular
JavaScript
111
star
30

ui-uploader

Customizable file uploader
JavaScript
108
star
31

ui-tour

A native tour-type directive that will lace easily-controllable tooltips throughout your app
HTML
94
star
32

AngularJs.tmbundle

AngularJs Textmate Bundle
87
star
33

angular-ui.github.com

Angular UI homepage
HTML
80
star
34

bower-ui-grid

Bower package for UI Grid
JavaScript
39
star
35

ui-scrollpoint

Add a 'ui-scrollpoint' class to elements when the page scrolls past them.
JavaScript
29
star
36

ui-event

Bind a callback to any event not natively supported by Angular
JavaScript
28
star
37

AngularJS-tern-plugin

A, slow'ish moving, WIP plugin for Tern that enables it to understand AngularJS dependency injection.
JavaScript
26
star
38

community

Placeholder repo for discussion
24
star
39

angular-ui-publisher

Helper component for building and publishing your angular modules as bower components
JavaScript
20
star
40

ui-leaflet-draw

angular directive for ui-leaflet to utilize Leaflet.Draw
CoffeeScript
16
star
41

ui-indeterminate

Toggle a checkbox input's special 'indeterminate' property
JavaScript
14
star
42

angular-ui-router-bower

Bower publishing for Angular UI-Router for ng1
14
star
43

ui-calendar2

Angular Native Calendar, inspired by ui-calendar
JavaScript
13
star
44

angular-ui-docs

Helper component for building your angular modules as bower components
JavaScript
10
star
45

ng-grid-legacy

ng-grid 2.x
JavaScript
5
star
46

builder

Build server for angular-ui
JavaScript
3
star
47

ui-position

Helper class used by a lot of angular projects on the web
1
star