1

I'm comfortable with the comparator function in Backbone.Collection and I'm also comfortable with the idea of sorting a collection and then redrawing the whole thing from a view. However, I'm not looking for that here.

I've got a collection that has been sorted (upon load). One view listens to the collection and is responsible for iterating through it on "reset". The models of the collection have their own view. Nothing out of the ordinary here.

However, the user is able to edit each model in-line, potentially changing the value of the attribute that is featured in the comparator function. Obviously one solution would be to just clear the whole collection's view, re-sort the collection, and then redraw all the models' views. But I'd like to avoid doing that if possible.

Ideally, I should be able to remove the altered model from the collection's view and then re-insert it at its new, appropriate, position in the collection view (so I'm only doing one DOM removal and one DOM addition - rather than clearing and then redrawing the entire collection of models). I could of course do this manually, without any help from backbone, but I thought I'd ask if there are any features of backbone that could make it easier, or at least more streamlined. Doing this completely outside of backbone seems like a hack, and it won't look pretty.

EleventyOne
  • 7,300
  • 10
  • 35
  • 40
  • I don't quite follow your question, but what do you mean by "clear the whole collection"? Why can't you invoke `sort` on the collection when your featured Attribute changes and listen for the `sort` event within your collection view and call `render`? – fbynite Oct 14 '13 at 04:26
  • I've edited the question to try to make it more clear. This is really a view problem, not a collection/sort problem. Obviously I failed to explain myself properly. Hopefully it's better now. – EleventyOne Oct 14 '13 at 04:34
  • So you're asking about changing the sort order of the DOM elements? – kinakuta Oct 14 '13 at 05:06
  • Kind of. I'm trying to make the order of the DOM elements match the (newly sorted) order of the collection's models, without having to re-draw every single one. – EleventyOne Oct 14 '13 at 05:53

1 Answers1

1

I think I know what you're getting at. Assuming you have access to the models and views in question, here's a basic approach:

// assumption: this is called on "change" event, only once
re_insert_item : function(model,m_view,collection,c_view) {

    // remove the model's view from the DOM
    m_view.$el.remove();

    // assuming there is a comparator, sort() will move the
    // model into the correct position of the collection. since
    // we're not doing a .remove and .add, we have to sort manually
    // (as per documentation instructions)
    collection.sort();

    // figure out the model that, based upon its sort position, our
    // edited model will come *before*
    var idx = collection.indexOf(model);
    var next_model = collection.at(idx+1);

    // insert our model's view into the DOM right above it's neighbour
    // this assumes you have some way to get a view for a given model,
    // which there isn't really a "standard" way to do (it seems)
    if ( next_model ) {
        var next_m_view = ??? // assume you have some way to get this
        next_m_view.$el.before(m_view.render().$el);
    }

    // this model is last in the list, so just append it to the
    // collection view (assuming the collection view houses the
    // master list as its $el)
    else {
        c_view.$el.append(m_view.render().$el);
    }
}

You'll have to change a bunch of it depending on: a) where you plan to put the code - i.e., where/how you're going to get the function params from; b) how you have your models and views linked together.

There was a (somewhat) similar question asked here on SO. However, in contrast to the answer I highlighted with the above link, I prefer not to use DOM traversal code if I can avoid it, instead relying on the ordering of backbone's collection.

Nevertheless, I think this is what you're looking for. If not, please be as specific as possible regarding what's missing.

Community
  • 1
  • 1
a.real.human.being
  • 878
  • 2
  • 6
  • 17
  • Epic. Answer. Thanks so much for the detailed response! So I guess I'll just keep a reference to each models' view within the model itself. – EleventyOne Oct 14 '13 at 06:04
  • 1
    You're welcome! :) As for the model/view links, that's not really a good way to go about it. Check out [this](http://stackoverflow.com/questions/11473898/find-a-backbone-js-view-if-you-know-the-model) SO thread for some ideas. – a.real.human.being Oct 14 '13 at 06:08