Search code examples
backbone.js

Backbone replace view / get view position


I have an application which is not optimally designed. I don't have time to re-write it, and need to find a solution to the following problem:

In my application new elements may be added to the collection, and there is a function in the collection view which decides whether to insert the new element at the top or the bottom:

if (someLogic) {
  this.$container.prepend( newEl );
} else {
  this.$container.append( newEl );
}

There is also the possibility to edit elements; in this case the application first destroys the old view, if there is any:

item.trigger('destroyView');

and then renders it. Somehow it was rendered in the same place it was previously:

+--------+           +--------+
|   x1   |           |   x1   |
+--------+           +--------+
|   x2   |           |   x2   |
+--------+   ====>   +--------+
|   x3   |           |   x3a  |
+--------+           +--------+
|   x4   |           |   x4   |
+--------+           +--------+

Now, due to some changes, the edited element is rendered either at the top or at the bottom of the collection view.

My question is: how do I render it in the same place it was previously.
I tried to add a listener on the model as explained here, but some of the programmatic logic seems to be broken.

Is there any way to:

  1. replace an existing view with a new rendered one?

    OR

  2. by iterating the container view elements, get the corresponding models? (the models have an attribute which indicates order, so I can use insertAfter or insertBefore)


Solution

  • I figured out that the solution is easier than I thought.

    In the place I get the new model, I can determine whether the model exists already or not.
    In case it exists, instead of destroying old view and render it again, I simply send a trigger so the view is rendered again, in the same place it was:

    container view:

    var model = this.collection.findWhere({id:newInteractionData.id});
    if (model) {
      model.trigger('render');
    } else {
      // here comes the old 'render' code
    }
    

    item view:

    this.listenTo(this.model, "render", this.render);