7

Related Questions -

BackboneJS best way to rearrange models in a collection while maintaining 0-indexed ordinal property for each model

How can I move a model within a collection?

I have a Backbone collection, visually represented in a list. This list is drag/droppable. Any item can be moved to an arbitrary position in the collection (ie - not a sort). I've seen some examples that use the collection's native remove/add to put the model in the right place. However, Backbone internally calls set when models are added, which then calls a bunch of methods related to events and sorts it at the end. Is there any downside to just splicing the model to the correct position?

Remove/Add: See examples in first linked question.

Splice: Second example

Function I'm currently using:

    moveTo: function(oldIndex, newIndex){
        oldIndex = oldIndex instanceof Backbone.Model ? this.at(oldIndex) : oldIndex;
        var spliced = this.models.splice(oldIndex, 1);
        this.models.splice(newIndex, 0, spliced[0]);
        this.trigger("move",[oldIndex,newIndex]);
    },
Community
  • 1
  • 1
iabw
  • 1,108
  • 1
  • 9
  • 24
  • 3
    Are you sure this isn't a sort? Drag'n'drop to move things around is manually changing the element indexes and an array/collection is something that is, more or less, sorted by index. – mu is too short Aug 18 '13 at 04:44
  • I guess 'technically' you can call it a sort, I just meant that it's an arbitrary one, not an automated one based off of properties of the array. But I think you're pointing out that this is equivalent to a 'sort', since both just re-arrange items, and thus Backbone has no issues with it. – iabw Aug 18 '13 at 11:13
  • My question might be better expressed as - "Is there ever a situation where you want to remove and re-add Models to a Collection, instead of manually 'sorting' them?" ;) – iabw Aug 18 '13 at 11:16

1 Answers1

13

I wrote this solution for my most recent project. It seems to be a similar interface to what you described - a sortable list. This method is bound to the collection.

reorder: function(new_index, original_index) {
    // If nothing is being changed, don't bother
    if (new_index === original_index) return this;
    // Get the model being moved
    var temp = collection.at(original_index);
    // Remove it
    collection.remove(temp);
    // Add it back in at the new index
    collection.add(temp, { at: new_index });
    return this;
}

Most of my own code has been removed, but that is the core functionality. Backbone's at option makes this really easy.

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
Sam Purcell
  • 815
  • 1
  • 6
  • 12
  • 3
    You may want to silence the `remove` and `add` calls to prevent unwanted changes on views listening to the collection and the models inside it. You may also want to create your own `move` event to let listeners react accordingly. – Emile Bergeron Jul 13 '16 at 20:03