AngularJS module for jQueryUI draggable and droppable


Last year, I played a lot with jQueryUI and mostly draggable/droppable along with AngularJS and it was a bit of a pain so I decided to write a directive for it which should make it easy for others to implement such functionalities.

Demos and much more

http://codef0rmer.github.com/angular-dragdrop/#/

Fork it on Github

https://github.com/codef0rmer/angular-dragdrop

and written test cases also 🙂
https://github.com/codef0rmer/angular-dragdrop/blob/master/test/index.html

Good Night!

If you found this article useful in anyway, feel free to donate me and receive my dilettante painting as a token of appreciation for your donation.
Advertisement

55th Neat thing built with AngularJS


I’m extremely glad to announce today that an application I’d built over months in AngularJS has now been listed on builtwith.angularjs.org

What’s in a name?

y’know like all the funky names, I named it eShell. Oh, wait, its not another terminal emulator. Rather, its an eLearning player – a building block for eLearning courses to be run on created with authoring tools. FYI, An eLearning player is a building block for more conventional eLearning courses. Its pretty basic though I’d a different vision when I decided to write it. You can learn more about it here and here.

I’ve covered:

  • jQueryUi Drag & Drop
  • Form Validation in AngularJS
  • Ordering/Sorting images
  • jPlayer integration to play audios

Working Demo

Update:

I’d decided to rewrite the application from the scratch and also written the steps how I did it.

Working Demo

eShell
eShell
If you found this article useful in anyway, feel free to donate me and receive my dilettante painting as a token of appreciation for your donation.

AngularJS + jQueryUI Drag & Drop


Checkout Angular Module to implement drag-and-drop more seemlessly

In this post, I’ve created a simple demo of integration of jQueryUI draggable/droppables in AngularJS. It’s pretty straight forward to understand the code as I’ve heavily commented it so I decided not to explain it in detail.

DEMO


<!DOCTYPE html>
<html ng-app="App">
<head>
<meta name="description" content="AngularJS + jQuery UI Drag-n-Drop" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" />
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap.min.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
<script>
// Bootstrap the Application
var App = angular.module('App', []);
// Set up a controller and define a model, list1 and list2 (empty)
App.controller('dndCtrl', function($scope) {
$scope.list1 = [
{name: 'AngularJS', reject: true},
{name: 'Is'},
{name: 'teh'},
{name: '@wesome'}
];
$scope.list2 = [];
});
// This makes any element draggable
// Usage: <div draggable>Foobar</div>
App.directive('draggable', function() {
return {
// A = attribute, E = Element, C = Class and M = HTML Comment
restrict:'A',
//The link function is responsible for registering DOM listeners as well as updating the DOM.
link: function(scope, element, attrs) {
element.draggable({
revert:true
});
}
};
});
// This makes any element droppable
// Usage: <div droppable></div>
App.directive('droppable', function($compile) {
return {
restrict: 'A',
link: function(scope,element,attrs){
//This makes an element Droppable
element.droppable({
drop:function(event,ui) {
var dragIndex = angular.element(ui.draggable).data('index'),
reject = angular.element(ui.draggable).data('reject'),
dragEl = angular.element(ui.draggable).parent(),
dropEl = angular.element(this);
if (dragEl.hasClass('list1') && !dropEl.hasClass('list1') && reject !== true) {
scope.list2.push(scope.list1[dragIndex]);
scope.list1.splice(dragIndex, 1);
} else if (dragEl.hasClass('list2') && !dropEl.hasClass('list2') && reject !== true) {
scope.list1.push(scope.list2[dragIndex]);
scope.list2.splice(dragIndex, 1);
}
scope.$apply();
}
});
}
};
});
</script>
</head>
<body ng-controller="dndCtrl" ng-cloak>
<div class='list1' droppable>
<div class='btn btn-info btn-block' ng-repeat="item in list1" data-index="{{$index}}" data-reject="{{item.reject}}" draggable>{{item.name}}</div>
</div>
<div class='list2' droppable>
<div class='btn btn-info btn-block' ng-repeat="item in list2" data-index="{{$index}}" data-reject="{{item.reject}}" draggable>{{item.name}}</div>
</div>
</body>
</html>

Updates: More advanced version by Mita Glefler below:


<!DOCTYPE html>
<html>
<head>
<meta name='description' content='AngularJS + jQuery UI Drag-n-Drop'/>
<title>JS Bin</title>
<link href='//ajax.googleapis.com/ajax/libs/jqueryui/1/themes/base/jquery-ui.css' rel='stylesheet'/>
<link href='//netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap.min.css' rel='stylesheet'>
<style>
#dnd-container {
margin-left: auto;
margin-right: auto;
margin-top: 20px;
width: 568px
}
#dnd-container .ui-droppable {
float: left;
border: 2px solid fuchsia;
width: 250px;
padding: 10px;
height: 208px;
border-radius: 10px;
margin-top: 20px;
}
</style>
</head>
<body>
<div ng-app='App' id='dnd-container' ng-controller='dndCtrl' ng-cloak>
<div ui-drop-listener='dropListener' data-model='someArrays.list0'>
<div ui-draggable ng-repeat='item in someArrays.list0' data-index='{{$index}}' class='btn btn-info btn-block'>
{{item.name}}
</div>
</div>
<div ui-drop-listener='dropListener' data-model='someArrays.list1' style='margin-left: 20px'>
<div ui-draggable ng-repeat='item in someArrays.list1' data-index='{{$index}}' class='btn btn-info btn-block'>
{{item.name}}
</div>
</div>
<div ui-drop-listener='dropListener' data-model='someArrays.list2'>
<div ui-draggable ng-repeat='item in someArrays.list2' data-index='{{$index}}' class='btn btn-info btn-block'>
{{item.name}}
</div>
</div>
<div ui-drop-listener='dropListener' data-model='someArrays.list3' style='margin-left: 20px'>
<div ui-draggable ng-repeat='item in someArrays.list3' data-index='{{$index}}' class='btn btn-info btn-block'>
{{item.name}}
</div>
</div>
</div>
<script src='//ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools-yui-compressed.js'></script>
<script src='//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js'></script>
<script src='//ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js'></script>
<script src='//ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js'></script>
<script>
(function () {
var app = angular.module('App', []);
app.controller('dndCtrl', ['$scope', 'someArrays', function ($scope, someArrays) {
$scope.someArrays = someArrays;
$scope.dropListener = function (eDraggable, eDroppable) {
var isDropForbidden = function (aTarget, item) {
if (aTarget.some(function (i) {
return i.name == item.name;
})) {
return {reason:'target already contains "' + item.name + '"'};
} else {
return false;
}
};
var onDropRejected = function (error) {
alert('Operation not permitted: ' + error.reason);
};
var onDropComplete = function (eSrc, item, index) {
console.log('moved "' + item.name + ' from ' + eSrc.data('model') + '[' + index + ']' + ' to ' + eDroppable.data('model'));
};
var eSrc = eDraggable.parent();
var sSrc = eSrc.data('model');
var sTarget = eDroppable.data('model');
if (sSrc != sTarget) {
$scope.$apply(function () {
var index = eDraggable.data('index');
var aSrc = $scope.$eval(sSrc);
var aTarget = $scope.$eval(sTarget);
var item = aSrc[index];
var error = isDropForbidden(aTarget, item);
if (error) {
onDropRejected(error);
} else {
aTarget.push(item);
aSrc.splice(index, 1);
onDropComplete(eSrc, item, index);
}
});
}
};
}]);
app.factory('someArrays', ['$q', '$timeout', function ($q, $timeout) {
var deferred = $q.defer();
$timeout(function () {
deferred.resolve({
someArrays:{
list0:[
{name:'AngularJS'},
{name:'Is'},
{name:'teh'},
{name:'@wesome'}
],
list1:[
{name:'AngularJS'}
],
list2:[
{name:'Is'},
{name:'rather good'}
],
list3:[
{name:'@wesome'},
{name:'MooTools'}
]}
});
}, 50);
return deferred.promise.then(function (result) {
return result.someArrays;
});
}]);
app.directive('uiDraggable', function () {
return {
restrict:'A',
link:function (scope, element, attrs) {
element.draggable({
revert:true
});
}
};
});
app.directive('uiDropListener', function () {
return {
restrict:'A',
link:function (scope, eDroppable, attrs) {
eDroppable.droppable({
drop:function (event, ui) {
var fnDropListener = scope.$eval(attrs.uiDropListener);
if (fnDropListener && angular.isFunction(fnDropListener)) {
var eDraggable = angular.element(ui.draggable);
fnDropListener(eDraggable, eDroppable, event, ui);
}
}
});
}
};
});
})();
</script>
</body>
</html>

If you found this article useful in anyway, feel free to donate me and receive my dilettante painting as a token of appreciation for your donation.