Help us understand the problem. What is going on with this article?

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

More than 5 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を設定することで、要素の活性非活性を制御できます。

サンプル

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

nogson
へっぽこデザイナーです。
https://satofaction.net/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away