Wlodzislav K.
Wlodzislav K.

Reputation: 404

Marionette doesn't render the sub-views when the parent is shown the second time

I want to reuse the views(previous opened screens) in the app, but the regions content disappear. How to prevent Marionette from doing this?

  var app = new Backbone.Marionette.Application();
  window.app = app;

  app.addRegions({
    root: 'body'
  });

  var View1 = Marionette.LayoutView.extend({
    template: _.template('<div>View1<div class="sub"></div></div>'),
      regions: {
        sub: '.sub'
      }
  });

  var View2 = Marionette.ItemView.extend({
    template: _.template('<div>View2</div>')
  });

  var SubView = Marionette.ItemView.extend({
    template: _.template('<div>SubView</div>')
  });

  var view1 = new View1();
  var view2 = new View2();
  var subView = new SubView();

  app.root.show(view1, { preventDestroy: true });
  view1.sub.show(subView, { preventDestroy: true });

  setTimeout(function() {
    app.root.show(view2, { preventDestroy: true });
    setTimeout(function() {
      app.root.show(view1, { preventDestroy: true });
    }, 500);
  }, 500);

or the fiddle http://jsfiddle.net/ndr7262y/

Upvotes: 0

Views: 391

Answers (1)

Quince
Quince

Reputation: 14990

So preventDestroy does not stop subViews within the region being destroyed just the actual region itself. Marionette by design trys to encourage the destruction of views and re initializing them so that clean up is all properly handled. One way round this though would be to listen to when view is being shown and then showing the sub

app.listenTo(view1, "show", function () {
          view1.sub.show(subView)
});

the only issue is that the sub view is still being destroyed so you could override the destroy method of the subView to not destroy the view, this gets a bit tricky to keep track off though as now you will have to manually ensure that the bindings are correctly applied/removed

  var SubView = Marionette.ItemView.extend({
      template: _.template('<div>SubView</div>'),
      destroy: function () {

          if (this.isDestroyed) {
              return;
          }

          var args = [].slice.call(arguments);

          this.triggerMethod.apply(this, ['before:destroy'].concat(args));

          // mark as destroyed before doing the actual destroy, to
          // prevent infinite loops within "destroy" event handlers
          // that are trying to destroy other views
          this.isDestroyed = false;
          this.triggerMethod.apply(this, ['destroy'].concat(args));

          // unbind UI elements????? well its not beng destoryed so probably don;t wantto do this
          //unless you manually handle rebind the events
          //this.unbindUIElements();
          return this;
      }
  });

end result http://jsfiddle.net/ndr7262y/2/

but a better way here would be re iniatalize the sub view when view 1 is shown

app.listenTo(view1, "show", function () {
           var subView = new SubView();
          view1.sub.show(subView)
});

and now you don;t have to worry about cleaning up or overriding the destroy method. http://jsfiddle.net/ndr7262y/4/

Upvotes: 1

Related Questions