Search code examples
javascriptbackbone.js

Backbone.js - sorting and iterating - comparator not working


I'm creating a collection of users, then adding the users, but when I print the users, they are not sorted.

I tried with .add and .create and I have the comparator set, so I thought it would sort automatically.

What am I missing?
I would like to at least loop through the users in sorted order.

My code with some comments

http://plnkr.co/edit/kMRdPfsjWDEIdHc22Ay0?p=preview

// A user
var User = Backbone.Model.extend({
  sync: function(){} // prevent send
});

// a collection
var Friends = Backbone.Collection.extend({
  comparator: 'lname',
  model: User
});

// instance
var friends = new Friends();

// loop through and add new users
for(var i=0; i<10; i++){
  friends.create({
    fname: createName(),
    lname: createName()
  });

  // tried with add, still not sorted
  // friends.add(new User({
  //   fname: createName(),
  //   lname: createName()
  // }));
}

// print what we have so far
console.log( friends.toJSON(), friends );

// when page is ready append to a table
$(document).ready(function(){
  var i = 0;
  friends.each(function( model ){
    i++;
    $('.friends tbody').append("<tr><td>" + i + "</td><td>" + model.get('lname') + "</td><td>" + model.get('fname') + "</td></tr>");
  });
})
;


// funtion to create random names 
function createName()
{
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    for( var i=0; i < 5; i++ ){
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return text;
}

Solution

  • In your case the comparator is doing the sorting alright, by using a lexical comparison. This means b comes after A, since it first checks for uppercase character precedence. What you need is a custom comparator function like this, that is case-insensitive:

    var Friends = Backbone.Collection.extend({
      // comparator: 'lname',
      comparator: function(a,b){
    
        a = a.get('lname').toLowerCase();
        b = b.get('lname').toLowerCase();  
        if (a < b) { return -1; }
        if (a > b) { return 1; }
        else { return 0; }
    
      },
      model: User
    });
    

    Here's the link to the forked Plunkr with the custom comparator function in place.