7

Having trouble showing, hiding, and then re-showing Marionette Layouts. I believe this problem also applies to regular Backbone Views and Marionette ItemViews as well though.

In summary, I have a parent view. When it is initialized, it creates two child layouts that are meant to be used as tab content. The problem is that when tab content from one tab is shown, then content from another tab is shown instead, when the original tab content is shown again, the events do not work anymore.

The child layouts are created in the initialize function of the parent layout and re-used because their states need to be preserved when navigation moves back to them.

Here is a sample application that demonstrates what I am talking about:

enter image description here

Here is a video showing the broken events: Video Link

Thanks so much!

Chris Dutrow
  • 48,402
  • 65
  • 188
  • 258

2 Answers2

4

The problem is that you don't create a new istance of your sub-layouts, and just re-use the one you initiate in your main layout. So when you change the content of your region the events get unbinded as part of the close() function of Marionette's View.

You should change your initialize function like that:

initialize: function(){
    _.bindAll(this);
    // CREATE SUB LAYOUTS
   this.tab1Layout = B.tab1Layout;
   this.tab2Layout = B.tab2Layout;
},

And call the layouts in this way:

// EVENT HANDLERS
on_show_tab_1_click: function(event){
    this.content.show(new this.tab1Layout());
},
on_show_tab_2_click: function(event){
    this.content.show(new this.tab2Layout());
}
Ingro
  • 2,841
  • 5
  • 26
  • 42
  • I need preserve the states of the child layouts. Is there any way to do this without re-creating the child layouts each time? – Chris Dutrow Sep 23 '12 at 22:32
  • I think you can override the `close()` function in your sub-layouts so the events will not be undinded when you close them. Check backbone marionette's source code for the original close function (row 182) and try to create a "light" version of it for your needs. – Ingro Sep 23 '12 at 22:42
2

If you don't want to re-initialize the tab views on every tab change you could call view.delegateEvents() manually:

// views[] is array of initialized tab views
// Swap from displaying views[0] to views[1]
currentTabIndex = 1
this.myRegion.show(views[currentTabIndex])
views[currentTabIndex].delegateEvents()

For preserving state, another option is to render both tabs and simply hide the inactive tab region:

// Assume both regions have initialised views, tab2Region is hidden, 
// tab1Region is shown.
// Swap between tabs:
this.tab1Region.$el.hide()
this.tab2Region.$el.show()
Rudolf Meijering
  • 1,559
  • 1
  • 14
  • 20