Tengo una aplicación Backbone.js con el complemento de marionetas. Hay una colección que se procesa con CompositeView (y ItemViews) y necesito ordenarla de la siguiente manera:

  1. El usuario puede reorganizar los elementos visualizados (usando el complemento ordenable jQuery) y esta preferencia del usuario se guarda en una cookie en forma de matriz de ID de modelo
  2. En cada recarga, quiero ordenar la colección obtenida para que esté en el mismo orden que esta matriz de orden de preferencia de usuario mencionada anteriormente.

Traté de ordenar la colección collection.models manualmente en el gancho de onRender y luego volver a renderizarla, pero este tipo de manipulación de colección simplemente "se siente mal" (y causa un bucle de renderizado interminable).

¿Existe algún tipo de solución más elegante para ordenar una colección para tener modelos en el mismo orden que los ID de modelo definidos en otra matriz?

1
Matic Jurglič 4 sep. 2014 a las 22:52

2 respuestas

La mejor respuesta

Intente utilizar el método Backbone.Collection # comparator en la colección que accederá a la cookie con una matriz de identificadores y lo usará para devolver 1 o -1.

las funciones de comparación toman dos modelos y devuelven -1 si el primer modelo debe venir antes que el segundo, 0 si son del mismo rango y 1 si el primer modelo debe venir después.

var MyCollection = Backbone.Collection.extend({

    comparator: function(model_a, model_b) {
        // In real app array comes from cookie
        var order = [5, 2, 1, 4, 3],
            a_index = order.indexOf(model_a.id),
            b_index = order.indexOf(model_b.id);

        if (a_index > b_index) {
            return 1;
        } else if (a_index < b_index) {
            return -1;
        } else {
            return 0;
        }
    }

});

var my_collection = new MyCollection([
    { id: 1 },
    { id: 2 },
    { id: 3 },
    { id: 4 },
    { id: 5 }
]);

alert(my_collection.pluck('id'));

Aquí está jsfiddle con este ejemplo

3
Eugene Glova 4 sep. 2014 a las 20:39

Un enfoque sería mapear sobre su lista "personalizada" de identificadores y modelos de retorno en la colección con esa identificación:

var items = [
  {id: 0, name: '1st', age: 40},
  {id: 1, name: '2nd', age: 50},
  {id: 2, name: '3rd', age: 60}
];

// order stored in cookie or localstorage ^^
var sorted = [2, 1, 0];

// our source collection
var collection = new Backbone.Collection(items);

// this could be implemented as a collection method if necessary
var sortedCollection = _.map(sorted, function (id) {
  return collection.get(id);
});


var sortedIds = sortedCollection.map(function (item) { return item.id })
console.log(sortedIds);
// [2, 1, 0]

jsbin con una vista de ejemplo

0
Nick Tomlin 4 sep. 2014 a las 21:54