Search code examples
javascriptbackbone.jsviewmarionette

Elegant way to append several views to a region in Marionette


Is there a more elegant way than the one below to append another view to a region? I'd like to append as many chat windows when a button is clicked, and destroy it when a button within the chat window is clicked.

The one below requires to keep track of an index per element:

var AppLayoutView = Backbone.Marionette.LayoutView.extend({
  template: "#layout-view-template",

  regions: {
      wrapperChat : '#wrapper-chat'
  }
  appendView: function ( incremennt, newView ){
     this.$el.append( '<div id="view'+increment+'" >' ) ;
     this.regionManager.addRegion( 'view'+increment , '#view'+increment )
     this['view'+increment].show ( newView ) ;
  }
});

// ChatView
var ChatView = Marionette.ItemView.extend({
  template: "#chat-template"
});

// Layout
var LayoutView = new AppLayoutView();
LayoutView.render();

// Append View
LayoutView.wrapper.appendView(++index, new ChatView());

Solution

  • Regions are designed to show a single View. Marionette's abstraction for repeating views is CollectionView, which renders an ItemView for each Model in a Collection.

    You add or remove Models from the Collection; Marionette handles the view updates for you.

    If your ChatView already has a model, use that. If not, you could add a trivial model to abstract away the index variable.

    // Collection for the Chat models. 
    // If you already have Chat Collection/Models, use that. 
    // If not, create a simple Collection and Models to hold view state, e.g.:
    var chats = new Backbone.Collection();
    
    // CollectionView "subclass"
    var ChatCollectionView = Marionette.CollectionView.extend({
      itemView: ChatView
    })
    
    // Add a single ChatCollectionView to your region
    var chatsView = new ChatCollectionView({ collection: chats });
    LayoutView.getRegion('wrapperChat').show();
    
    // To add a ChatView, add a Model to the Collection
    var nextChatId = 0;
    chart.addChat(new Backbone.Model({ id: nextChatId++ }));
    
    // To remove a chat, remove its model
    chart.remove(0);