これを行うには、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のようにコンパレータ機能がある場合は、モデルを削除してコレクションに追加し直す必要はありません。また、ビュー自体を再レンダリングする必要がない場合もあります。
注:他の回答と比較して、コレクションを直接更新するのではなく、アイテムのモデルインスタンスに更新する必要があることを通知する方が正しいと感じました。どちらのアプローチも有効です。ここでの他の答えは、モデルファーストのアプローチを採用するのではなく、コレクションに直接行きます。自分にとって意味のある方を選んでください。