AngularJS

AngularJSで、リストをドラック&ドロップで入れ替える為のメモ

More than 3 years have passed since last update.


やりたいこと

下記のようなリストをドラック&ドロップで順番を入れ替えたい


  • リスト1

  • リスト2

  • リスト3


準備

ui-sortableライブラリを使用します。

他にもng-sortableなど似たライブラリがあったのですが、ui-sortableがシンプルだったのでこちらを使うことにしました。

https://github.com/angular-ui/ui-sortable


インストール

bower install angular-ui-sortable --save

※ ui-sortableの他に、jQuryと、jQuery.UIも必要です。


ライブラリを読み込む


javascript

angular.module('myApp', ['ui.sortable']);



使い方


最もシンプルな設定方法

入れ替えの制御をしたい要素を、scopeに入れます。


javascript

angular.module('App', ['ui.sortable'])

.controller('AppCtrl', ['$scope', function($scope) {
$scope.items = ["いれかえたい", "とてもいれかえたい", "なんとかいれかえたい"];
}]);

入れ替えたい項目の親要素に、ui-sortable属性を設定。

scopeで入れた要素を、ng-modelに入れる。


html

<body ng-app="App" ng-controller="AppCtrl">

<ul ui-sortable ng-model="items">
<li ng-repeat="item in items">{{ item }}</li>
</ul>
</body>

cssでカーソルをmoveに設定すると、動かせそうな感じになります。

もしくは後述する、optionでcursor: "move"を設定する。


css

li{

cursor:move;
}

サンプル

ユーザー側で入れ替えたデータは、ng-modelに反映されるので、controllerのscopeから取得できます。


Optionを使う


参考

http://api.jqueryui.com/sortable/


Optionの設定方法

ui-sortable属性に追加して使用します。


html

  <ul ui-sortable="sortableOptions" ng-model="items">

<li ng-repeat="item in items">{{ item }}</li>
</ul>


javascript

 angular.module('App', ['ui.sortable'])

.controller('AppCtrl', ['$scope', function($scope) {
$scope.items = ["いれかえたい", "とてもいれかえたい", "なんとかいれかえたい"];
$scope.sortableOptions = {
axis: 'y'
};
}]);

下記のような書き方でもいいみたいです。


html

  <ul ui-sortable="{axis:'y'}" ng-model="items">

<li ng-repeat="item in items">{{ item }}</li>
</ul>


各オプションの機能


axis

移動方向を制御できる。


javascript

   //横方向に固定

$scope.sortableOptions = {
axis: 'x'
};

//縦方向に固定
$scope.sortableOptions = {
axis: 'y'
};


サンプル


update

モデルデータが変更された際に実行される


javascript

angular.module('App', ['ui.sortable'])

.controller('AppCtrl', ['$scope', function($scope) {
$scope.items = ["いれかえたい", "とてもいれかえたい", "なんとかいれかえたい"];
$scope.sortableOptions = {
update: function() {
alert('ok')
}
};
}]);

サンプル

特定の要素だけ移動をキャンセルするには下記のようにupdateの引数を使って、キャンセルする。

ただ、他を入れ替えると入れ替わっちゃうので、使い方がちょっと違うのかもしれない。


javascript

angular.module('App', ['ui.sortable'])

.controller('AppCtrl', ['$scope', function($scope) {
$scope.items = ["いれかえたい", "とてもいれかえたい", "動かさないで!!", "なんとかいれかえたい"];
$scope.sortableOptions = {
update: function(e, ui) {
if (ui.item.sortable.model === "動かさないで!!") {
ui.item.sortable.cancel();
}
}
};
}]);

サンプル


update以外のイベント

updateの他に下記のようなイベントが取得できる。


javascript

angular.module('App', ['ui.sortable'])

.controller('AppCtrl', ['$scope', function($scope) {
$scope.items = ["いれかえたい", "とてもいれかえたい", "なんとかいれかえたい"];

$scope.sortableOptions = {
start: function(e, ui) {
console.log('start')
},
stop: function(e, ui) {
console.log('stop')
},
activate: function() {
console.log('activate')
},
deactivate: function() {
console.log('deactivate')
},
beforeStop: function() {
console.log('beforeStop')
}
};
}]);



connectWith

connectWithを設定することで、違うmodel間での入れ替えが可能になる。

connectWithには、関連させるui-sortableのセレクタを指定する。


html

<body ng-app="App" ng-controller="AppCtrl">

<ul class="box" ui-sortable="sortableOptions" ng-model="items1">
<li ng-repeat="item in items1">{{ item }}</li>
</ul>
<ul class="box" ui-sortable="sortableOptions" ng-model="items2">
<li ng-repeat="item in items2">{{ item }}</li>
</ul>
</body>


javascript

angular.module('App', ['ui.sortable'])

.controller('AppCtrl', ['$scope', function($scope) {
$scope.items1 = ["いれかえたい", "とてもいれかえたい", "なんとかいれかえたい"];

$scope.items2 = ["いいいいい", "あああああ", "ううううう"];

$scope.sortableOptions = {
connectWith: ".box"
};
}]);


サンプル


placeholder

placeholderは入れ替え位置をドラッグ中に表示することができます。

placeholderには、class名を指定することで、表示を変更できます。


javascript

angular.module('App', ['ui.sortable'])

.controller('AppCtrl', ['$scope', function($scope) {
$scope.items1 = ["いれかえたい", "とてもいれかえたい", "なんとかいれかえたい"];

$scope.sortableOptions = {
placeholder:"placeholder"
};
}]);



css

.placeholder{

border:1px dotted #ccc;
height:30px;
background-color:#eee;
}

サンプル


opacity

opacityを設定することで、ドラック中の要素の透明度を調整できます。


javascript

angular.module('App', ['ui.sortable'])

.controller('AppCtrl', ['$scope', function($scope) {
$scope.items1 = ["いれかえたい", "とてもいれかえたい", "なんとかいれかえたい"];

$scope.sortableOptions = {
opacity:0.5
};
}]);


サンプル


disabled

disabledを設定することで、要素の活性非活性を制御できます。

サンプル

他にもたくさんオプションがあるので、こちらをみていただくと参考になると思います。