0

I am facing some architecture issue in backbonejs with nested collection. I have collection of models and inside each model it can contains collection of same model as childrens. so inside parent view render I am rendering child collection and appending its dom to parentview. It is working perfectly fine.

But on parent model change I am re-rendering its view that is causing its childrens to render again. But when parents model changes I don't to create chidldren dom as child collection have no change. Can I utilize children dom without re-rendering it. Is there any way I achieve it?

Parent View Code:

RowView.prototype.initialize = function(options) {
      this.childCollection = options.childCollection;
      this.listenTo(this.model, "change", this.render);
}
RowView.prototype.render = function() {
        var existingControls = this.model.get("controls").toJSON();
        this.childCollection = this.model.get("controls");
        this.childCollection.bind('add', this.addOneChild, this);
        this.childCollection.bind('reset', this.resetChildrens, this);
        this.childCollection.reset(existingControls, this);
    };
   RowView.prototype.addOneChild = function(respModel) {
      view = new RowViewChildView({
        model: respModel,
        parentView: this
      });

     this.$el.find('.childrens').append(view.render().el);
    };

   RowView.prototype.resetChildrens = function(currentCollection) {
      this.$el.find(".childrens").html('');
      return this.addAllChildrens();
    };

    RowView.prototype.addAllChildrens = function() {
      return this.childCollection.each(this.addOneChild, this);
    };

I don't want to loose child view event also.

Thanks in advance

No one
  • 1,130
  • 1
  • 11
  • 21

2 Answers2

1

unfortunately I cannot comment yet so I'll create an answer.

I am not entirly sure what you are trying to achieve, as it looks like your render method only contains code for rendering children and no code specific to rendering the parent, did you leave this out?

However you could try to have a render and a rerender function. The rerender function would only render the part of the Parent DOM that has changed (everything below parent-markup).

render: function () {
    //render everything below .parent
}
rerender: function () {
    //render stuff below parent-mark-up
}

The HTML could be split

<div class="parent">
 <div class="parent-markup"></div>
 <div class="children"></div>
</div>

If you do need to render the whole parent element and want to reuse the child DOM u can just safe the el and then append it again, afterwards use this.delegateEvents(); to make sure Events a being bubbled up again.

In general I would put the listeners into the initialize function and it is recommended to use this.listenTo(this.childCollection , 'add', this.callback);

Backbonejs: .on vs .listenTo vs .bind

Finally I would recommend using the modular syntax like so

var RowView = Backbone.View.extend({
    initialize: function(options) {}
    render: function() {}
});

Update: Here is a fiddle: https://jsfiddle.net/gs4r8k10/30/

Robin
  • 177
  • 1
  • 8
  • Hi Robin.. Thanks for your answer but my problem is that on change of parentmodel it is rendering its view that is also rendering child view. I don't want to render childview if parent model is changing.. I want to reuse childview dom as its rendering is very costly – No one Jul 09 '19 at 09:42
  • But you could change `this.listenTo(this.model, "change", this.render);` to `this.listenTo(this.model, "change", this.rerender);` and then in `rerender` only update the parent dom but not the children? Or you could (as said above) save `el` of every child and then append ist again and call `this.delegateEvents();` – Robin Jul 09 '19 at 10:47
  • Hi, I am saving el of children contains but when I am appending and calling this.delegateEvents() then child events not working. – No one Jul 09 '19 at 13:38
0

You can use jQuery detach() to detach existing childrens DOM and append them again after parent is re-renders.

If could be something like

if(this.childrenAlreadyRendered){
  // special performant rendering with detach
}

in your render method. does such smart rendering.

T J
  • 42,762
  • 13
  • 83
  • 138