1

I have a Backbone.js app with marionette plugin. There's a collection which renders with a CompositeView (and ItemViews) and I need to sort it in the following way:

  1. User can rearrange rendered ItemViews (using jQuery sortable plugin) and this user preference gets saved in a cookie in a form of array of model IDs
  2. On each reload, I want to sort the fetched collection to be in the same order as this aforementioned array of user preference order.

I tried to sort collection.models array manually in the onRender hook and then re-rendering it, but this kind of collection manipulation just "feels wrong" (and causes an endless render loop).

Is there some kind of a more elegant solution to sort a collection to have models in the same order as model IDs defined in some other array?

1

2 Answers 2

3

Try to use Backbone.Collection#comparator method on collection which will access cookie with array of ids and uses it to return 1 or -1.

comparator functions take two models, and return -1 if the first model should come before the second, 0 if they are of the same rank and 1 if the first model should come after.

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'));

Here is jsfiddle with this example

Sign up to request clarification or add additional context in comments.

Comments

0

One approach would be to map over your "custom" list of ids and return models in the collection with that id:

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 with an example view

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.