:ok_hand: Drag and drop so simple it hurts

Subscribe to updates I use angular-dragula

Statistics on angular-dragula

Number of watchers on Github 491
Number of open issues 47
Average time to close an issue 8 days
Main language HTML
Average time to merge a PR 2 days
Open pull requests 9+
Closed pull requests 2+
Last commit 10 months ago
Repo Created almost 3 years ago
Repo Last Updated 3 months ago
Size 1.35 MB
Homepage https://bevacqua....
Organization / Authorbevacqua
Latest Releasev1.2.2
Page Updated
Do you use angular-dragula? Leave a review!
View open issues (47)
View angular-dragula activity
View on github
Latest Open Source Launches
Trendy new open source projects in your inbox! View examples

Subscribe to our mailing list

Evaluating angular-dragula for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)


Drag and drop so simple it hurts

Official Angular wrapper for dragula.



Try out the demo!


You can get it on npm.

npm install angularjs-dragula --save

Or bower, too.

bower install angularjs-dragula --save


You'll need to pass in angularDragula to your module when booting up your application. angularjs-dragula takes your angular instance and uses it to register its own module, service, and directive.

var angular = require('angular');
var angularDragula = require('angularjs-dragula');

var app = angular.module('my-app', [angularDragula(angular)]);


This package isn't very different from dragula itself. I'll mark the differences here, but please refer to the documentation for dragula if you need to learn more about dragula itself.


There's a dragula directive (as seen in the demo) that allows you to group containers together, as long as they belong to the same scope. That grouping of containers is called a bag.

<div dragula='"bag-one"'></div>
<div dragula='"bag-one"'></div>
<div dragula='"bag-two"'></div>


ng-repeat creates a new isolate scope, which can sometimes cause issues with dragging between a bag with multiple containers. To avoid this you can pass in the scope you want the bag to be stored on (and fire events on) by setting the dragula-scope directive on the bag element.

<ul ng-controller="ItemsController">
  <li ng-repeat="item in items" dragula='"bag-one"' dragula-scope="$parent"></li>


If your ng-repeat is compiled from array, you may wish to have it synced. For that purpose you need to provide model by setting the dragula-model attribute on the bag element

<ul ng-controller="ItemsController">
  <li ng-repeat="item in items" dragula='"bag-one"' dragula-model="items"></li>

The standard drop event is fired before the model is synced. For that purpose you need to use the drop-model event. The same behavior exists in the remove event. Therefore is the remove-model event. Further details are available under Events

drake options

If you need to configure the drake (there's only one drake per bag), you'll have to use the dragulaService.

app.controller('ExampleCtrl', ['$scope', 'dragulaService',
  function ($scope, dragulaService) {
    dragulaService.options($scope, 'third-bag', {
      removeOnSpill: true


Whenever a drake instance created with the dragula directive emits an event, that event is replicated on the Angular $scope where the drake has an associated bag, and prefixed with the name on its bag.

<div dragula='"evented-bag"'></div>
app.controller('ExampleCtrl', ['$scope', function ($scope) {
    .$on('evented-bag.over', function (e, el) {
    .$on('evented-bag.out', function (e, el) {

Note that these derived events don't expose the DOM elements directly. The elements get wrapped in angular.element calls.

Special Events for angularjs-dragula

Event Name Listener Arguments Event Description
drop-model el, target, source same as normal drop, but model was synced, just available with the use of dragula-model
remove-model el, container same as normal remove, but model was synced, just available with the use of dragula-model


This service exposes a few different methods with which you can interact with dragula in the Angular way.

dragulaService.add(scope, name, drake)

Creates a bag scoped under scope and identified by name. You should provide the entire drake instance. Typically, the directive takes care of this step.

dragulaService.options(scope, name, options)

Sets the options used to instantiate a drake. Refer to the documentation for dragula to learn more about the options themselves.

dragulaService.find(scope, name)

Returns the bag for a drake instance. Contains the following properties.

  • name is the name that identifies the bag under scope
  • drake is the raw drake instance itself

dragulaService.destroy(scope, name)

Destroys a drake instance named name scoped under scope.



angular-dragula open issues Ask a question     (View All Issues)
  • over 1 year is it good to send dropElmModel with 'drop-model'?
  • over 1 year Ability to specify placeholder item
  • over 1 year Drag and drop action will be frozen for no reason
  • over 1 year Models and containers in different order making dropped elements show up in wrong containers
  • over 1 year Unexpected behavior on third level nested tables
  • over 1 year dragula - always drag to the list end
  • almost 2 years dragula directive should remove the container on "$destroy" of its element
  • almost 2 years Mix of $rootScope and $scope with different bag not updating the model
  • almost 2 years Selenium Drag doesn't fire drag emit
  • almost 2 years Any way to drag and drop nested Firebase objects instead of arrays?
  • almost 2 years can not drop at all
  • almost 2 years How to do this: dragula-model='{{vm.myvar}}' ??
  • almost 2 years Multiple Drag and Drop
  • almost 2 years Scroll & Scroll between bags
  • almost 2 years RequireJS
  • almost 2 years ngRepeat:dupes error, with source or destaination items being replaced with null
  • almost 2 years How to get drag and drop target and source
  • almost 2 years le.moves is not a function
  • about 2 years Dragging & dropping element outside any dragular container
  • about 2 years Windows phone not working
  • about 2 years Pass value in controller
  • about 2 years drake container is not removed when dom element is removed
  • about 2 years Dragging elements without preview leads to strange offset
  • about 2 years How to place dragging element on drop position?
  • about 2 years Is it possible to disable the draggability without removing the directive?
  • about 2 years Uncaught ReferenceError: angularDragula is not defined
  • about 2 years models are lost when inside ng-if
  • over 2 years Cannot use dragula on existing directive
  • over 2 years Dynamic bag name
  • almost 3 years Do not rely on scope
angular-dragula open pull requests (View All Pulls)
  • Snap mirror container to cursor as specified in options. Originally ā€¦
  • Remove container from drake containers array when directive element iā€¦
  • Fix for drake drop error
  • Remove the container on element's "$destroy"
  • model data with model events
  • Bugs #100, #103 and #109 fixed
  • Fix filenames and expose models on drop and remove
  • Fix filenames that were still angular-dragula to angular-dragulajs
  • fixed reference to angular-dragula.js in index page
angular-dragula questions on Stackoverflow (View All Questions)
  • Using Angular Dragula without RequireJS
angular-dragula list of languages used
angular-dragula latest release notes
v1.2.2 Body of Lies

fixes #47

v1.2.1 The Postman Always Rings Twice
  • fixes #45
v1.2.0 Mr. Right
  • Starting to doing better releases
  • Fix issue with drake.models not being defined
  • Keep model in sync
  • Fix model watcher
Other projects in HTML