var app = angular.module('demoApp', ['ui.router','dndLists']);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/errorPage');
$stateProvider
.state('default',{
url:'/',
templateUrl:'defaultPage.tpl.html'
})
.state('parent', {
abstract:true,
url: '/parent',
templateUrl:'parent.tpl.html',
controller: 'demoCtrl'
})
.state('parent.child',{
url:'/child',
templateUrl: 'childPage.tpl.html'
})
.state('errorPage', {
url: '/errorPage',
templateUrl: 'errorPage.html'
});
});
app.controller('demoCtrl',['$scope', function($scope) {
$scope.listArray = {
selected:null,
lists:{"A":[]}
};
var arraySize = 0;
$scope.addToArray = function(data) {
if(typeof data !== "undefined"){
if(data.length > 0){
arraySize += 1;
$scope.listArray.lists.A.push({
id:arraySize,
label: data,
isSelected: false,
isDeleted: false
});
storeItLocal();
$scope.iserror = false;
}
else $scope.iserror = true;
}
else $scope.iserror = true;
}
if(localStorage.getItem('listsArray')){
$scope.listArray.lists.A = JSON.parse(localStorage.getItem('listsArray'));
}
$scope.checked = function(data) {
$scope.listArray.lists.A[data].isSelected = !$scope.listArray.lists.A[data].isSelected;
storeItLocal();
}
$scope.dlt = function(index) {
$scope.listArray.lists.A.splice(index,1);
storeItLocal();
$scope.$watch('listArray', function() {
console.log($scope.listArray.lists.A);
});
}
$scope.move = function() {
storeItLocal();
};
var storeItLocal = function(){
localStorage.setItem('listsArray',JSON.stringify($scope.listArray.lists.A));
return this;
}
}]);
app.directive('ngEnter', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind("keydown", function(e) {
if (e.which == 13) {
scope.$apply(function() {
scope.$eval(attrs.ngEnter);
scope.todoList = "";
});
}
});
}
}
});
<!DOCTYPE html>
<html ng-app="demoApp">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.4.x" src="https://code.angularjs.org/1.4.9/angular.js" data-semver="1.4.9"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.2/ui-bootstrap-tpls.min.js"></script>
<script src="angular-drag-drop.min.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<script src="app.js"></script>
</head>
<body ng-controller="demoCtrl">
<nav class="navbar">
<ul class="nav navbar-nav">
<li><a href="#/">Home</a></li>
<li><a href="#/parent/child">ToDo List</a></li>
</ul>
</nav>
<div ui-view></div>
</body>
</html>
/* Put your css in here */
ul li{
list-style: none;
}
.clr{
clear: both;
}
.todoContainer{
width: 385px;
margin: 2px 0;
padding: 2%;
border: 1em solid lightgray;
background-color: #2F1269;
color: #fff;
text-transform: uppercase;
cursor: grabbing;
cursor: -webkit-grabbing;
}
.simpleDemo ul[dnd-list],
.simpleDemo ul[dnd-list] > li {
position: relative;
}
/**
* The dnd-list should always have a min-height,
* otherwise you can't drop to it once it's empty
*/
.simpleDemo ul[dnd-list] {
/* min-height: 42px;
padding-left: 0px;*/
}
/**
* The dndDraggingSource class will be applied to
* the source element of a drag operation. It makes
* sense to hide it to give the user the feeling
* that he's actually moving it.
*/
.simpleDemo ul[dnd-list] .dndDraggingSource {
display: none;
}
/**
* An element with .dndPlaceholder class will be
* added to the dnd-list while the user is dragging
* over it.
*/
.simpleDemo ul[dnd-list] .dndPlaceholder {
display: block;
background-color: #ddd;
min-height: 42px;
width: 385px;
}
/**
* The dnd-lists's child elements currently MUST have
* position: relative. Otherwise we can not determine
* whether the mouse pointer is in the upper or lower
* half of the element we are dragging over. In other
* browsers we can use event.offsetY for this.
*/
.simpleDemo ul[dnd-list] li {
/* background-color: #fff;
border: 1px solid #ddd;
border-top-right-radius: 4px;
border-top-left-radius: 4px;*/
display: block;
/* padding: 10px 15px;
margin-bottom: -1px;*/
}
/**
* Show selected elements in green
*/
.simpleDemo ul[dnd-list] li.selected {
background-color: #dff0d8;
color: #3c763d;
}
<section>
<h3>Quick dragable list </h3>
<div ui-view class="controller"></div>
</section>
<h3>Simply add it and drag it.</h3>
<div>
<input type="text" ng-model="todoList" ng-enter="addToArray(todoList)">
<span ng-if="iserror">Required</span>
<hr>
<div class="simpleDemo" ng-repeat="(listName, list) in listArray.lists">
<ul dnd-list="list">
<li class="row-fluid todoContainer" ng-repeat="item in list" dnd-draggable="item"
dnd-moved="list.splice($index, 1); move()"
dnd-effect-allowed="move"
ng-if="!item.isDeleted">
<div class="col-sm-6 checkbox">
<label>
<input type="checkbox" ng-click="checked($index)" ng-checked="item.isSelected">
{{$index}}<span ng-bind="item.label"></span>
</label>
</div>
<div ng-if="item.isSelected" class="col-sm-6">
<button type="button" class="btn btn-warning" ng-click="dlt($index)">Delete</button>
</div>
<div class="clr"></div>
</li>
</ul>
</div>
</div>
<pre class="code">{{listArray | json}}</pre>
<div>Sorry Page Not Found</div>
/**
* angular-drag-and-drop-lists v1.4.0
*
* Copyright (c) 2014 Marcel Juenemann marcel@juenemann.cc
* Copyright (c) 2014-2016 Google Inc.
* https://github.com/marceljuenemann/angular-drag-and-drop-lists
*
* License: MIT
*/
angular.module("dndLists",[]).directive("dndDraggable",["$parse","$timeout","dndDropEffectWorkaround","dndDragTypeWorkaround",function(e,n,r,t){return function(a,d,o){d.attr("draggable","true"),o.dndDisableIf&&a.$watch(o.dndDisableIf,function(e){d.attr("draggable",!e)}),d.on("dragstart",function(i){return i=i.originalEvent||i,"false"==d.attr("draggable")?!0:(i.dataTransfer.setData("Text",angular.toJson(a.$eval(o.dndDraggable))),i.dataTransfer.effectAllowed=o.dndEffectAllowed||"move",d.addClass("dndDragging"),n(function(){d.addClass("dndDraggingSource")},0),r.dropEffect="none",t.isDragging=!0,t.dragType=o.dndType?a.$eval(o.dndType):void 0,i._dndHandle&&i.dataTransfer.setDragImage&&i.dataTransfer.setDragImage(d[0],0,0),e(o.dndDragstart)(a,{event:i}),void i.stopPropagation())}),d.on("dragend",function(i){i=i.originalEvent||i
var f=r.dropEffect
a.$apply(function(){switch(f){case"move":e(o.dndMoved)(a,{event:i})
break
case"copy":e(o.dndCopied)(a,{event:i})
break
case"none":e(o.dndCanceled)(a,{event:i})}e(o.dndDragend)(a,{event:i,dropEffect:f})}),d.removeClass("dndDragging"),n(function(){d.removeClass("dndDraggingSource")},0),t.isDragging=!1,i.stopPropagation()}),d.on("click",function(n){o.dndSelected&&(n=n.originalEvent||n,a.$apply(function(){e(o.dndSelected)(a,{event:n})}),n.stopPropagation())}),d.on("selectstart",function(){this.dragDrop&&this.dragDrop()})}}]).directive("dndList",["$parse","$timeout","dndDropEffectWorkaround","dndDragTypeWorkaround",function(e,n,r,t){return function(a,d,o){function i(e,n,r){var t=E?e.offsetX||e.layerX:e.offsetY||e.layerY,a=E?n.offsetWidth:n.offsetHeight,d=E?n.offsetLeft:n.offsetTop
return d=r?d:0,d+a/2>t}function f(){var e
return angular.forEach(d.children(),function(n){var r=angular.element(n)
r.hasClass("dndPlaceholder")&&(e=r)}),e||angular.element("<li class='dndPlaceholder'></li>")}function l(){return Array.prototype.indexOf.call(D.children,v)}function g(e){if(!t.isDragging&&!y)return!1
if(!c(e.dataTransfer.types))return!1
if(o.dndAllowedTypes&&t.isDragging){var n=a.$eval(o.dndAllowedTypes)
if(angular.isArray(n)&&-1===n.indexOf(t.dragType))return!1}return o.dndDisableIf&&a.$eval(o.dndDisableIf)?!1:!0}function s(){return p.remove(),d.removeClass("dndDragover"),!0}function u(n,r,d,o){return e(n)(a,{event:r,index:d,item:o||void 0,external:!t.isDragging,type:t.isDragging?t.dragType:void 0})}function c(e){if(!e)return!0
for(var n=0;n<e.length;n++)if("Text"===e[n]||"text/plain"===e[n])return!0
return!1}var p=f(),v=p[0],D=d[0]
p.remove()
var E=o.dndHorizontalList&&a.$eval(o.dndHorizontalList),y=o.dndExternalSources&&a.$eval(o.dndExternalSources)
d.on("dragenter",function(e){return e=e.originalEvent||e,g(e)?void e.preventDefault():!0}),d.on("dragover",function(e){if(e=e.originalEvent||e,!g(e))return!0
if(v.parentNode!=D&&d.append(p),e.target!==D){for(var n=e.target;n.parentNode!==D&&n.parentNode;)n=n.parentNode
n.parentNode===D&&n!==v&&(i(e,n)?D.insertBefore(v,n):D.insertBefore(v,n.nextSibling))}else if(i(e,v,!0))for(;v.previousElementSibling&&(i(e,v.previousElementSibling,!0)||0===v.previousElementSibling.offsetHeight);)D.insertBefore(v,v.previousElementSibling)
else for(;v.nextElementSibling&&!i(e,v.nextElementSibling,!0);)D.insertBefore(v,v.nextElementSibling.nextElementSibling)
return o.dndDragover&&!u(o.dndDragover,e,l())?s():(d.addClass("dndDragover"),e.preventDefault(),e.stopPropagation(),!1)}),d.on("drop",function(e){if(e=e.originalEvent||e,!g(e))return!0
e.preventDefault()
var n,t=e.dataTransfer.getData("Text")||e.dataTransfer.getData("text/plain")
try{n=JSON.parse(t)}catch(d){return s()}var i=l()
return o.dndDrop&&(n=u(o.dndDrop,e,i,n),!n)?s():(n!==!0&&a.$apply(function(){a.$eval(o.dndList).splice(i,0,n)}),u(o.dndInserted,e,i,n),"none"===e.dataTransfer.dropEffect?"copy"===e.dataTransfer.effectAllowed||"move"===e.dataTransfer.effectAllowed?r.dropEffect=e.dataTransfer.effectAllowed:r.dropEffect=e.ctrlKey?"copy":"move":r.dropEffect=e.dataTransfer.dropEffect,s(),e.stopPropagation(),!1)}),d.on("dragleave",function(e){e=e.originalEvent||e,d.removeClass("dndDragover"),n(function(){d.hasClass("dndDragover")||p.remove()},100)})}}]).directive("dndNodrag",function(){return function(e,n,r){n.attr("draggable","true"),n.on("dragstart",function(e){e=e.originalEvent||e,e._dndHandle||(e.dataTransfer.types&&e.dataTransfer.types.length||e.preventDefault(),e.stopPropagation())}),n.on("dragend",function(e){e=e.originalEvent||e,e._dndHandle||e.stopPropagation()})}}).directive("dndHandle",function(){return function(e,n,r){n.attr("draggable","true"),n.on("dragstart dragend",function(e){e=e.originalEvent||e,e._dndHandle=!0})}}).factory("dndDragTypeWorkaround",function(){return{}}).factory("dndDropEffectWorkaround",function(){return{}})
<h3>
Drag & drop in angularJS
</h3>
<p>
It is achievable using this directive https://github.com/marceljuenemann/angular-drag-and-drop-lists by Marcel Juenemann.
</p>