I\'m trying to recreate the Draggable + Sortable functionality from jQuery and can\'t get the dropped element to go into my array of objects.
I want t
There is no angular-magic that can help you find the position of a new or moved element, but it's easy to do with jQuery. I've created an example of the jQueryUI-demo wrapping sortable and draggable in directives:
http://plnkr.co/edit/aSOlqR0UwBOXgpQSFKOH?p=preview
- Drag me down
- {{item.name}}
Value of my my-draggable
is the id to the corresponding my-sortable
-element. my-draggable is otherwise pretty straight forward:
app.directive('myDraggable',function(){
return {
link:function(scope,el,attrs){
el.draggable({
connectToSortable: attrs.myDraggable,
helper: "clone",
revert: "invalid"
});
el.disableSelection();
}
}
})
In my-sortable
I listen to the deactivate
event which indicates that an element has been dropped. from
is the position of the element in the array that is the source of ng-repeat. ng-repeat creates a child scope for each element with an $index variable indicating the position of the current element in the array. If $index is undefined I know that it's a new element (might be a better way to determine this, but it works for this example). to
is the new position of the item. I $emit a 'my-sorted' event if an existing element was moved or a 'my-created' event if a new item was added.
app.directive('mySortable',function(){
return {
link:function(scope,el,attrs){
el.sortable({
revert: true
});
el.disableSelection();
el.on( "sortdeactivate", function( event, ui ) {
var from = angular.element(ui.item).scope().$index;
var to = el.children().index(ui.item);
if(to>=0){
scope.$apply(function(){
if(from>=0){
scope.$emit('my-sorted', {from:from,to:to});
}else{
scope.$emit('my-created', {to:to, name:ui.item.text()});
ui.item.remove();
}
})
}
} );
}
}
})
In the controller I create the items-array and listen to the events:
$scope.items = [
{name:'Item 1'},
{name:'Item 2'},
{name:'Item 3'},
{name:'Item 4'},
];
$scope.$on('my-sorted',function(ev,val){
// rearrange $scope.items
$scope.items.splice(val.to, 0, $scope.items.splice(val.from, 1)[0]);
})
$scope.$on('my-created',function(ev,val){
// create new item at position
$scope.items.splice(val.to, 0,
{name:'#'+($scope.items.length+1)+': '+val.name});
})
As you can see, when you add or move an element the model in the scope gets updated.
These directives are not very general - you might have to do some adjustment to get them to work with your application.