新しい要素または移動した要素の位置を見つけるのに役立つ角度マジックはありませんが、jQuery を使用すると簡単に行うことができます。ディレクティブでソート可能およびドラッグ可能をラップする jQueryUI-demo の例を作成しました。
http://plnkr.co/edit/aSOlqR0UwBOXgpQSFKOH?p=preview
<ul>
<li my-draggable="#sortable" class="ui-state-highlight">Drag me down</li>
</ul>
<ul my-sortable id="sortable">
<li class="ui-state-default" ng-repeat="item in items">{{item.name}}</li>
</ul>
my の値はmy-draggable
、対応する要素の IDmy-sortable
です。my-draggable は、それ以外の場合は非常に簡単です。
app.directive('myDraggable',function(){
return {
link:function(scope,el,attrs){
el.draggable({
connectToSortable: attrs.myDraggable,
helper: "clone",
revert: "invalid"
});
el.disableSelection();
}
}
})
要素がドロップされたことを示すイベントをmy-sortable
リッスンします。ng-repeat のソースである配列内の要素の位置です。ng-repeat は、配列内の現在の要素の位置を示す $index 変数を使用して、各要素の子スコープを作成します。$index が定義されていない場合、それが新しい要素であることがわかります (これを判断するためのより良い方法かもしれませんが、この例では機能します)。アイテムの新しい位置です。既存の要素が移動された場合は 'my-sorted' イベントを $emit し、新しいアイテムが追加された場合は 'my-created' イベントを $emit します。deactivate
from
to
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();
}
})
}
} );
}
}
})
コントローラーで items-array を作成し、イベントをリッスンします。
$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});
})
ご覧のとおり、要素を追加または移動すると、スコープ内のモデルが更新されます。
これらのディレクティブはあまり一般的ではありません。アプリケーションで動作するようにするには、何らかの調整が必要になる場合があります。