Я думаю, что ваш подход должен состоять из двух отдельных шагов:
1) С одной стороны вы обновляете данные на сервере
2) С другой стороны, вы обновляете коллекцию на стороне клиента
Итак, вы в порядке на шаге 1, вы сказали, что это работает.
На шаге 2 вы можете воспользоваться программированием, управляемым событиями.
Логика такова:
- ВЫ ТОЛЬКО ДОБАВЛЯЕТЕ ОДИН ЭЛЕМЕНТ В КОЛЛЕКЦИЮ (collection.add (модель) запускает событие add).
- В коллекции вы прослушиваете событие add. Когда вы его ловите, вы снова сортируете свою коллекцию (collection.sort запускает событие reset)
- В вашем представлении для списка (questionView в вашем случае) вы прослушиваете событие сброса коллекции, и после его запуска вы повторно визуализируете свое представление
Пример кода:
1) QuestionView: удален addItem и упрощен addNewItem (он не должен отображаться)
window.QuestionView = Backbone.View.extend({
el: $("#content"),
events : {
'sortupdate ol#questions': 'sortStuff'
},
initialize: function(collection) {
this.collection = new QuestionsList;
_.bindAll(this, 'addOne', 'addAll', 'addNewItem');
this.collection.bind('add', this.addNewItem);
this.collection.bind('reset', this.addAll);
this.collection.fetch({
data: { quiz_id: $qid },
processData:true
});
},
render: function() {},
sortStuff: function() {
$this = this;
$.ajax({
url: "/hq/reorder/",
type: "POST",
data: $("#questions").sortable("serialize")+"&id="+$qid,
dataType: 'json',
success: function(data) {
}
});
},
//METHOD addItem REMOVED!!!
addNewItem: function(question) {
this.collection.add({title: 'New title goes here'}); //***IT FIRES AN ADD EVENT
},
addOne: function(question) {
var view = new ItemView({model: question, parent: this});
this.$("#questions").prepend(view.render().el);
},
addAll: function() {
this.collection.each(this.addOne);
return false;
}
});
2) коллекция перехватывает событие добавления и сортирует (запускает событие сброса)
вы всегда можете обработать это в QuestionView, ваша функция инициализации становится.
initialize: function(collection) {
this.collection = new QuestionsList;
_.bindAll(this, 'addOne', 'addAll', 'addNewItem');
this.collection.bind('add', this.addNewItem);
this.collection.bind('reset', this.addAll);
this.collection.fetch({
data: { quiz_id: $qid },
processData:true
});
//ADD THIS*****
this.collection.on('add', function(){
this.collection.sort();
});
},
3) третий шаг уже сделан, вы просто заново визуализируете представление
Лучше всего, если вы сортируете элементы в своей коллекции, определяя новую функцию «компаратор», которая использует атрибут «позиция» вашего списка
что-то вроде (в QuestionView)
this.collection.comparator: function(){
return this.collection.get("position");
}
так, чтобы элементы были упорядочены по позиции СТОРОНА КЛИЕНТА
** EDIT **
Функция инициализации изменена. Выборка используется вместо «сортировки», что бесполезно, если атрибут «позиция» каждого элемента в коллекции не обновляется.
initialize: function(collection) {
this.collection = new QuestionsList;
_.bindAll(this, 'addOne', 'addAll', 'addNewItem');
this.collection.bind('add', this.addNewItem);
this.collection.bind('reset', this.addAll);
this.collection.fetch({
data: { quiz_id: $qid },
processData:true
});
//ADD THIS*****
this.collection.on('add', function(){
this.collection.fetch();
});