Ответ 1
Я сделал это, используя jQuery UI Sortable, чтобы вызвать событие в представлении элемента при отбрасывании элемента. Затем я могу вызвать другое событие в представлении элемента, которое включает модель в качестве данных, к которым привязано представление коллекции. Тогда представление коллекции может отвечать за обновление порядка сортировки.
Рабочий пример
http://jsfiddle.net/7X4PX/260/
jQuery UI Sortable
$(document).ready(function() {
$('#collection-view').sortable({
// consider using update instead of stop
stop: function(event, ui) {
ui.item.trigger('drop', ui.item.index());
}
});
});
Событие stop привязано к функции, которая запускает drop
в DOM node для элемента с индексом элемента (предоставляемый jQuery UI) в качестве данных.
Просмотр позиции
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;
}
});
Событие drop привязано к функции drop
, которая запускает событие update-sort
в представлении элементов DOM node с данными [this.model, index]
. Это означает, что мы передаем текущую модель и индекс (из jQuery UI sortable), кто связан с событием 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
обновляется по каждому оставшемуся элементу, а порядок элементов по идентификатору отправляется на сервер для хранения состояния.
Collection
Application.Collection.Items = Backbone.Collection.extend({
model: Application.Model.Item,
comparator: function(model) {
return model.get('ordinal');
},
});
В коллекции есть функция comparator, которая заказывает коллекцию с помощью ordinal
. Это сохраняет отображаемый порядок элементов в синхронизации, так как "порядок по умолчанию" коллекции теперь равен значению атрибута ordinal
.
Обратите внимание, что существует некоторое дублирование усилий: модель не требуется удалять и добавлять обратно в коллекцию, если коллекция имеет функцию компаратора, как это делает jsfiddle. Кроме того, представление может не понадобиться для повторной рендеринга.
Примечание: по сравнению с другим ответом, я чувствовал, что было правильнее уведомлять экземпляр модели элемента, который нужно было обновить, а не непосредственно в коллекции. Оба подхода действительны. Другой ответ здесь идет непосредственно на коллекцию, а не на подход, основанный на модели. Выберите, что имеет для вас больше смысла.