46

jQuery UI の Sortable を使用してソートできるようにしたい Backbone.js コレクションがあります。特別なことは何もありません。並べ替えたいリストがあるだけです。

問題は、ソート後にアイテムの現在の順序を取得し、それをコレクションに伝える方法がわからないことです。Sortable はそれ自体をシリアル化できますが、コレクションに提供する必要があるモデル データが得られません。

理想的には、コレクション内のモデルの現在の順序の配列を取得し、コレクションのリセット メソッドを使用できるようにしたいのですが、現在の順序を取得する方法がわかりません。現在のモデル順序で配列を取得するためのアイデアや例を共有してください。

4

3 に答える 3

81

これを行うには、jQuery UI Sortableを使用して、アイテムがドロップされたときにアイテムビューでイベントをトリガーします。次に、コレクションビューがバインドされているデータとしてモデルを含むアイテムビューで別のイベントをトリガーできます。コレクションビューは、並べ替え順序の更新を担当できます。

実例

http://jsfiddle.net/7X4PX/260/

jQueryUIソート可能

$(document).ready(function() {
    $('#collection-view').sortable({
        // consider using update instead of stop
        stop: function(event, ui) {
            ui.item.trigger('drop', ui.item.index());
        }
    });
});

停止イベントは、dropアイテムのインデックス(jQuery UIによって提供される)をデータとして持つアイテムのDOMノードでトリガーされる関数にバインドされます。

アイテムビュー

Application.View.Item = Backbone.View.extend({
    tagName: 'li',
    className: 'item-view',
    events: {
        'drop' : 'drop'
    },
    drop: function(event, index) {
        this.$el.trigger('update-sort', [this.model, index]);
    },        
    render: function() {
        $(this.el).html(this.model.get('name') + ' (' + this.model.get('id') + ')');
        return this;
    }
});

ドロップイベントは、データを使用してアイテムビューのDOMノードでイベントdropをトリガーする関数にバインドされます。つまり、現在のモデルとそのインデックス(jQuery UIから並べ替え可能)を、イベントにバインドされている人に渡します。update-sort[this.model, index]update-sort

アイテム(コレクション)ビュー

Application.View.Items = Backbone.View.extend({
    events: {
        'update-sort': 'updateSort'
    },
    render: function() {
        this.$el.children().remove();
        this.collection.each(this.appendModelView, this);
        return this;
    },    
    appendModelView: function(model) {
        var el = new Application.View.Item({model: model}).render().el;
        this.$el.append(el);
    },
    updateSort: function(event, model, position) {            
        this.collection.remove(model);

        this.collection.each(function (model, index) {
            var ordinal = index;
            if (index >= position) {
                ordinal += 1;
            }
            model.set('ordinal', ordinal);
        });            

        model.set('ordinal', position);
        this.collection.add(model, {at: position});

        // to update ordinals on server:
        var ids = this.collection.pluck('id');
        $('#post-data').html('post ids to server: ' + ids.join(', '));

        this.render();
    }
}); 

Itemsビューはイベントにバインドされ、update-sort関数はイベントによって渡されたデータ(モデルとインデックス)を使用します。モデルがコレクションから削除され、ordinal残りの各アイテムの属性が更新され、IDによるアイテムの順序がサーバーに送信されて状態が保存されます。

コレクション

Application.Collection.Items = Backbone.Collection.extend({
    model: Application.Model.Item,
    comparator: function(model) {
        return model.get('ordinal');
    },
});

コレクションには、コレクションを。で並べ替えるコンパレータ関数が定義されていordinalます。これにより、コレクションの「デフォルトの順序」がordinal属性の値によるものになるため、アイテムのレンダリングされた順序の同期が維持されます。

作業が重複していることに注意してください。コレクションにjsfiddleのようにコンパレータ機能がある場合は、モデルを削除してコレクションに追加し直す必要はありません。また、ビュー自体を再レンダリングする必要がない場合もあります。

:他の回答と比較して、コレクションを直接更新するのではなく、アイテムのモデルインスタンスに更新する必要があることを通知する方が正しいと感じました。どちらのアプローチも有効です。ここでの他の答えは、モデルファーストのアプローチを採用するのではなく、コレクションに直接行きます。自分にとって意味のある方を選んでください。

于 2012-04-13T23:50:13.180 に答える
6

Backbone.CollectionViewを使用するだけです。

var collectionView = new Backbone.CollectionView( {
  sortable : true,
  collection : new Backbone.Collection
} );

出来上がり!

于 2014-01-10T19:33:35.237 に答える