Синхронизация массива с отсортированным Backbone.Collection

Я пытаюсь синхронизировать отсортированный Backbone.Collection с другим списком, например, массивом JavaScript. Я использую следующий код ( jsfiddle):

var coll = new Backbone.Collection();
coll.comparator = "label";

var list = []

coll.on("add", function (model, collection, options) {
    list.splice(collection.indexOf(model), 0, model.get("label"));
});

coll.add([
    {label: "1"},
    {label: "3"},
    {label: "5"},
    {label: "4"},
    {label: "2"}
]);

В этом примере это приводит к следующему списку: 1, 2, 3, 5, 4, Основная причина в том, что в обработчике события добавления коллекция Backbone.Collection уже заполнена всеми моделями, а массив JS - нет. Поскольку события добавления инициируются в порядке вставки, а не в порядке сортировки, это приводит к неправильному порядку в массиве.

Как бы я изменил свой подход к синхронизации / добавить обработчик, чтобы все заработало?

2 ответа

Решение

Сначала нужно послушать sort событие

    this.listenTo(this.collection, 'sort', this.sortList);

Затем добавьте data-id идентификатор для каждого элемента списка

    var li = $("<li>", { "data-id": model.get("label") }).html(model.get("label"));

А затем сортировать элементы HTML на основе неравной позиции

    sortList: function(collection, options) {
        collection.forEach(function(model, index) {
            var li1 = this.$el.children().eq(index),
                li2;
            if (model.get("label") != li1.data("id")) {
                li2 = this.$el.children("[data-id=" + model.get("label") + "]");
                li1.before(li2);
            }
        }, this);
    },

Ссылка jsfiddle http://jsfiddle.net/n0fdmb8a/3/

Похоже, ваша ошибка происходит во время инициализации:

var coll = new Backbone.Collection([
    {label: "1"},
    {label: "3"},
    {label: "5"},
    {label: "4"},
    {label: "2"}
], { comparator: 'label' )

var list = coll.pluck('label')

// Assuming your add-handler works, you can keep that around for future add's
coll.on("add", function (model, collection, options) {
    list.splice(collection.indexOf(model), 0, model.get("label"));
});

Если этого недостаточно, вам нужно будет поработать над sync событие, которое происходит после add"S. Тем не менее, я бы порекомендовал liпросто слушает coll затем полностью перерисовывает всякий раз, когда coll загорается add, remove, или же sort, Это полностью предотвратило бы попытку синхронизировать два массива друг с другом, что в программировании - нет. Как правило, вы должны создать структуру данных для обработки этого взаимодействия, но вашей коллекции должно быть достаточно:

var LabelsView = Backbone.Collection.extend({
    el: '#my-list',
    template: '<% coll.each(function(model){ %> <li><%- model.get("label") %></li><% }); %>',
    initialize: function(){
        this.listenTo(this.collection, 'add remove sort', this.render)
    }
    render: function(){
        this.$el.html( this.template({ coll: this.collection }) )
    }
}) 

var labelView = new LabelsView({ collection: coll })
Другие вопросы по тегам