Сортировать базовую коллекцию на основе атрибутов модели

У меня есть базовая коллекция, которая отображается в таблице. Я хотел бы сделать таблицу сортируемой на основе определенных атрибутов, которые имеет коллекция, например "task_status", "task_group". Я читаю базовую документацию о collection.comparator, nd collection.sort. Как я могу это сделать?

Ответ 1

Функция comparator используется для сравнения двух моделей в коллекции и может сравнивать их любым (последовательным) способом, которым она хочет. В частности, он может выбрать, какой атрибут модели использовать, чтобы вы могли иметь что-то подобное в своей коллекции:

initialize: function() {
    this.sort_key = 'id';
},
comparator: function(a, b) {
    // Assuming that the sort_key values can be compared with '>' and '<',
    // modifying this to account for extra processing on the sort_key model
    // attributes is fairly straight forward.
    a = a.get(this.sort_key);
    b = b.get(this.sort_key);
    return a > b ?  1
         : a < b ? -1
         :          0;
}    

а затем вам понадобятся некоторые методы в коллекции для изменения sort_key и вызовите sort:

sort_by_thing: function() {
    this.sort_key = 'thing';
    this.sort();
}

В старых Backbones вызов sort вызывает событие "reset", тогда как более новые версии будут запускать событие "sort". Чтобы охватить оба случая, вы можете прослушивать оба события и повторно отображать:

// in the view...
initialize: function() {
    this.collection.on('reset sort', this.render, this);
}

Демо: http://jsfiddle.net/ambiguous/7y9CC/

Вы также можете использовать listenTo вместо on, чтобы избежать зомби:

initialize: function() {
    this.listenTo(this.collection, 'reset sort', this.render);
}

Демо: http://jsfiddle.net/ambiguous/nG6EJ/

Ответ 2

@mu-is-too-short ответ хорош, за исключением более простого способа сравнить значения полей:

Самый простой способ сортировки коллекции на основе поля - предоставить функцию компаратора, которая возвращает точное значение поля, которое вы хотите отсортировать. Этот тип компаратора заставляет Backbone вызывать функцию sortBy вместо sort, которая затем выполняет это сложное сравнение по своему усмотрению, и вам не нужно беспокоиться о логике.

Таким образом, по сути, вам не нужно предоставлять сложную функцию компаратора, если у вас нет более сложной потребности в определении порядка.

var myCollection = Backbone.Collection.extend({
    sort_key: 'id', // default sort key
    comparator: function(item) {
        return item.get(this.sort_key);
    },
    sortByField: function(fieldName) {
        this.sort_key = fieldName;
        this.sort();
    }
});

После этого вы можете просто вызвать коллекцию sortByField -функция со строкой, представляющей ключ, который вы хотите отсортировать. Например:

collection.sortByField('name');

Модифицированная короткая демонстрация @my-is-too-short: http://jsfiddle.net/NTez2/39/

Ответ 3

@jylauril ответ помогает чрезвычайно, но необходимо изменить демо (возможно, небольшие изменения в позвоночнике, так как он был опубликован?)

Похоже, вам нужно вызвать рендер после сортировки.

$('#by-s').click(function() {
  c.sortByField('s');
  v.render();
});

Обновлено @my-is-too-short demo: http://jsfiddle.net/NTez2/13/