1

I am having my backbone collection as below:

var model1 = new Backbone.Model({mode: 'EX'});
var model2 = new Backbone.Model({mode: 'AB'});
var model3 = new Backbone.Model({mode: 'DF'});
var model4 = new Backbone.Model({mode: 'AB'});
var model5 = new Backbone.Model({mode: 'DF'});
var model6 = new Backbone.Model({mode: 'AB'});

var myCollection =  new backbone.Collection([model1,model2,model3,model4,model5, model6]);

Now I want this collection to be sorted in some business order, let say all models having 'DF' mode first then all models having 'AB' mode second and lastly models with mode 'EX'.

Required Output

/*my Collection.models should contains array of models in following sequence
after sorting */
[model3, model5, model2, model4, model6, model1]

I have another java script object based on which I will be deciding this sequence of modes. e.g.

var enum = {
  1: 'DF',
  2: 'AB',
  3: 'EX'
}

So here string sorting is not useful. Can somebody suggest how can I write comparator on my backbone collection to accomplish this sorting

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Shaggy
  • 315
  • 2
  • 9
  • 23

2 Answers2

2

You need to extend default Backbone.Collection with a custom comparator:

var priority= ['DF', 'AB', 'EX'];

var Collection = Backbone.Collection.extend({
  comparator: function(a, b) {
    return priority.indexOf(a.get('mode')) > priority.indexOf(b.get('mode'));
  }
});
var myCollection = new Collection([{
  mode: 'EX'
}, {
  mode: 'AB'
}, {
  mode: 'DF'
}, {
  mode: 'AB'
}, {
  mode: 'DF'
}, {
  mode: 'AB'
}]);
console.log(myCollection.pluck('mode'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>

or with an object map:

var priority = {
  1: 'DF',
  2: 'AB',
  3: 'EX'
}

var Collection = Backbone.Collection.extend({
  comparator: function(a, b) {
    var i = _.findKey(priority, function(val) {
      return val === a.get('mode')
    });
    var j = _.findKey(priority, function(val) {
      return val === b.get('mode')
    });
    return i > j;
  }
});
var myCollection = new Collection([{
  mode: 'EX'
}, {
  mode: 'AB'
}, {
  mode: 'DF'
}, {
  mode: 'AB'
}, {
  mode: 'DF'
}, {
  mode: 'AB'
}]);
console.log(myCollection.pluck('mode'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
T J
  • 42,762
  • 13
  • 83
  • 138
  • Thanks @TJ for your reply, I followed the object map method as given by Tholl in 2nd answer – Shaggy Jun 03 '16 at 12:11
1

I would flip the enumerator so you can index it easily.

var enumerator = {
  DF: 1,
  AB: 2,
  EX: 3
};

var YourModel = Backbone.Model.extend({
  defaults: {
    mode: ''
  }
});

var YourCollection = Backbone.Collection.extend({
  model: YourModel,
  comparator: function(m) {
    return enumerator[m.get('mode')];
  }
});

var yourCollection = new YourCollection([
  { mode: 'EX' },
  { mode: 'AB' },
  { mode: 'DF' },
  { mode: 'AB' }
]);

console.log(yourCollection.pluck('mode')); // ["DF", "AB", "AB", "EX"]
Tholle
  • 108,070
  • 19
  • 198
  • 189