user1473339
user1473339

Reputation:

Backbone.marionnette - Rebinding events vs creating new view

I have a Layout that has several tabs. Clicking one of these tabs will show the appropriate composite view in the page's content region. After navigating back and forth between different tabs I noticed that the composite views have lost their native bindings to render on collection reset and model changes.

Is there a way I should be rebinding the events being used in _initialEvents of a composite view when showing a view for a second time, or should I be creating a new composite view every I show a tab?

Currently I am creating all my views in initialize of my Layout and then using show with the view when a tab is clicked.

initialize: function(){
    _.bindAll(this);

    //     Tabs
    this.places_page   = new Places_Layout();
},

show_places_page: function(){

    this.content.show(this.places_page);
    this.places_page.delegateEvents();
},

Upvotes: 6

Views: 385

Answers (4)

Raju Bera
Raju Bera

Reputation: 1018

You should not create all the views inside the initialize as this will cause you memory leaks that's why you should do dynamic creation of the views. Also I would suggest create a common function for showing a view in your content region to increase the code re-usability. I would suggest you something like following solution:

//define the regions of your layout view
regions: {
  content: '#content'
},
//Maintain a config for the tab content view classes.
contentViews: {
  tab1: Tab1View,
  tab2: Tab2View,
  tab3: Tab3View
},
//keeps all the view instances
viewInstances: {},
/*
 * show tab function is called when you click a tab item.
 * Consider each tab has a attribute for tab name.
 * For example HTML of your one tab is like:
 * <div data-tab-name="tab_name">Tab <tab_name></div> 
 */
showTab: function (e) {
  var tabName = $(e.currentTarget).attr("data-tab-name");
  /*
   * code for showing selected tab goes here...
   */

  //check and create the instance for the content view
  if (!this.viewInstances[tabName]) {
      this.viewInstances[tabName] = new this.contentViews[tabName]();
  }
  //Then here you are actually showing the content view
  this.content.show(this.viewInstances[tabName]);
  this.viewInstances[tabName].delegateEvents(); //this is to rebind events to the view.
}

Upvotes: 0

Uuid
Uuid

Reputation: 2546

You don not have to create a Layout/Item/Composite/Collection view each time you switch from tab to tab, on the contrary you can save the content in a variable just the way you are doing, the problem you have is that the variable is being re-declared each time you want to render the content. The solution is that you have to verify if that variable (this.places_page) is declared if not append it to the view so when you call it more times it will be holding the same layout view without any problem, just note that when you render the main view (the one holding the regions) the nested child views(in regions) will be lost until new navegation through them.

initialize: function(){
    _.bindAll(this);

    // You can asign a diferent variable for each view so when you call show_places_page it will render with the same view.

    if (!this.places_page){
         this.places_page   = new Places_Layout();
    }

    // other tab        
    if (!this.other_page){
         this.other_page   = new OtherPage_Layout();
    }

},

show_places_page: function(){

    this.content.show(this.places_page);
    this.places_page.delegateEvents();
},

Upvotes: 1

deven98602
deven98602

Reputation: 1110

Marionette(v.1) onwords uses Backbone.BabySitter to manage child views .

In your case you do the same. Just create a containter to store all tab view. Later query the container to return the view you need to display.

this.tabViewsContainer = new Backbone.ChildViewContainer();
this.tabViewContainer.add(new CustomView(),'tab1');
this.tabViewContainer.add(new SecondCustomView(),'tab2');

To Later Show the view just do this

var custv = container.findByCustom("tab1");
this.content.show(custv);

In close method your layout view successfully close all view in container

this.tabViewsContainer.each(function(view){view.close()});

Upvotes: 0

martin308
martin308

Reputation: 716

This does not sound like the best approach to me.

You should use the layout's region managers to show views without needing functions like you have defined.

I would go for this approach

var view = new CustomView();
layout.content.show(view);`

then later on:

var newView = new SecondCustomView();
layout.content.show(newView);

If you want to continue down the road that you are on then you would probably be best to use this approach:

initialize: function () {
    _.bindAll(this);
},
show_places_page: function () {
    var placesLayout = new Places_Layout();
    this.content.show(placesLayout);
}

Does that make sense?

Its hard to suggest the best course of action without seeing more structure around this.

Is there a reason that you are creating the views in initialize?

Upvotes: 0

Related Questions