Retrieving index position of item added to Backbone.js Collection

11,486

Solution 1

If you're dealing with a simple scenario of adding a model to a collection with the add method, then you only need to call the indexOf method with that model, after adding it.

var myModel = new MyModel({some: "data"});

var myCollection = new MyCollection();
myCollection.add(myModel);

var index = myCollection.indexOf(myModel);

Solution 2

UPDATED

If you want to know the "index" of an element in a collection with underscore you can use indexOf.

Could you add a bigger sample of your code maybe in a fiddle so I can understand better what you want to do? Because for example if the elements in the collection are not primitive types (no ints or Strings but javascript objects) indexOf can present problems because objects with the same value that are different references wouldn't be considered equal by indexOf.

UPDATED 2

You could try doing this:

var cids = this.collection.map(function(elem){ return elem.cid; });
var index = _(cids).indexOf(myModel.cid);
Share:
11,486
Jack
Author by

Jack

Updated on June 09, 2022

Comments

  • Jack
    Jack almost 2 years

    If I add an item to a Collection how can I find the position at which it was added? The Underscore.js documentation for add suggests the only way to achieve this is by binding to the add event.

    Is there any other way? If not, then how can I reteive the index from my callback? I tried providing a callback of:

    foo:function(model, options) {
      console.log("foo: " + options.index);
    },
    

    but options.index is undefined. I bind to the event with this code:

    this.collection.bind('add', this.foo);
    

    and add an item with this code:

    this.collection.add(myNewItem);
    

    The model in the collection is:

    MyModel = Backbone.Model.extend({
    defaults : {
       key:undefined,
       myObj:undefined,
    },
    

    The collection is:

    MyModel List = Backbone.Collection.extend({
          model: MyModel,
    
    initialize: function() {
       this.comparator = function(aModel) {
       return aModel.get('key'); 
      };
     }});
    

    I am adding the model to the collection with:

     var key = "always_the_same";
    var mm = new MyModel({key:key});
    this.collection.add(mm);
    var index = this.collection.sortedIndex(mm , this.collection.comparator));
    

    Update

    The problem is (I think), the comparator function is used for indexOf and sortedIndexOf, therefore two objects with the same key are effectively the same object as far as the comparator function is concerned.

    I had hoped* that the CID would be used to ensure the object was actually the object I'm looking for in the already sorted collection. However it seems not. I guess one possible solution is to change my comparator function to include the CID:

    initialize: function() {
            this.comparator = function(aModel) {
              return aModel.get('key') + aModel.cid; 
            };
          },
    

    The models remain sorted according to their key value, but the following code returns the correct index position:

    this.collection.sortedIndex(myModel, this.collection.comparator);
    

    Feels hacky :( Can any one offer their opinion on this?

  • Jack
    Jack about 12 years
    How is a counter the same as an index position? My collection has a comparator function which keeps Items in alphabetical order. Therefore, when a item is added, it won't just be appended to the end of the Collection.
  • txominpelu
    txominpelu about 12 years
    Ah, then you can just create another temporal collection with the new element added and then with indexOf get the index where the element has been added.
  • txominpelu
    txominpelu about 12 years
    @Jack Sorry I haven't understood the question but if what you want to do is get what's the index of an element in a collection with underscore you can always use: indexOf . I've update the response based on that. However if that's not what you're looking for or it doesn't work for you, Could you give the source code of your problem so that I can understand it better?
  • Jack
    Jack about 12 years
    indexOf always returns 0, even though my comparator method is called and the item ends up at a different index position from 0. Is is not good to call indexOf immediately after add()?
  • Jack
    Jack about 12 years
    Unfortunately this answer does not resolve my problem either, even though the question seems to describe my problem exactly.
  • Jack
    Jack about 12 years
    After some investigation it seems the problem is the model instance being added to the collection does not contain any unique attributes, therefore the previously added model instance is being matched.
  • Jack
    Jack about 12 years
    I have updated my question with what I believe is the problem.
  • 1nfiniti
    1nfiniti almost 11 years
    do you know of any way of passing this information into the model's template at render time?