15

Problem

Using a Backbone.Marrionette.Layout to present some tabular data. The <tbody> portion of the table is a Backbone.Marionette.Region that is meant to display a Backbone.Marionette.CollectionView.

I can not figure out how to do this using Marionette's "Regions" without messing up the table display by inserting an extra HTML element inside the <tbody> element.

Example Code

The Layout looks like this:

Backbone.Marionette.Layout.extend({
    template:...
    regions:{
        list_region: '#list-region'
    }
    onRender:function(){
        var collection = new TheCollection()
        var collectionView = new TheCollectionView({
            collection: collection
        })
        // PROBLEM: The region seems to needs its own HTML element,
        //   and the CollectionView also seems to need its on HTML
        //   element, but as far as I can see, there is only room 
        //    for one element: <tbody>?
        this.list_region.show(collectionView);
});

The template for the Layout comprises the entire table:

<table>

    <tbody id='list-region'>

    </tbody>

    <tfoot id='footer-region'>
        Some other stuff goes here that is not a collection, so I was able 
        to make the View's 'tagName' property 'tr', which worked fine.
    </tfoot>

</table>

Any suggestions?

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

2 Answers2

16

Is the intent of this layout solely to facilitate a table? If so, you should look at using a CompositeView instead.


RowView = Marionette.ItemView.extend({
  tagName: "tr",
  template: ...
});

TableView = Marionette.CompositeView.extend({
  template: ...,

  childView: RowView,

  childViewContainer: "#list-region"
});

That's pretty much it. This will render all of your itemViews in to the tbody.

Trav McKinney
  • 988
  • 8
  • 24
Derick Bailey
  • 72,004
  • 22
  • 206
  • 219
  • Just wanted to write a quick thank-you. I've already a referred back to this a few times. – Chris Dutrow Aug 23 '12 at 12:19
  • 1
    In this case, what if you wanted to use an `ItemView` for aggregate data in a `tfoot`, would you just manually handle that as a child view since you cannot use the region model for that? Is that a use case for [Backbone.Babysitter](https://github.com/marionettejs/backbone.babysitter) with the `CompositeView`? – Paul Tyng Jun 24 '13 at 12:58
  • @PaulTyng - I have that exact same issue. The tfoot is itself a region. I'm going to have to rethink my layouts and views. – Adrian Lynch Jul 11 '14 at 09:40
  • 1
    CompositeView is deprecated and will be removed. In addition, if you need an empty view that does not include headers or footers, if one does not use collection view one must resort to hackery to remove the extra material. https://github.com/marionettejs/backbone.marionette/issues/828#issuecomment-178823618 – Myer Jun 22 '16 at 20:31
2

Marionette 3 deprecated the CompositeView class. Instead, a region can now overwrite its el with the rendered contents of the inner View with the new replaceElement option.

See this example to render a table:

var RowView = Marionette.View.extend({
  tagName: 'tr',
  template: '#row-template'
});

var TableBody = Marionette.CollectionView.extend({
  tagName: 'tbody',
  childView: RowView
});

var TableView = Marionette.View.extend({
  tagName: 'table',
  className: 'table table-hover',
  template: '#table',

  regions: {
    body: {
      el: 'tbody',
      replaceElement: true
    }
  },

  onRender: function() {
    this.showChildView('body', new TableBody({
      collection: this.collection
    }));
  }
});

var list = new Backbone.Collection([
  {id: 1, text: 'My text'},
  {id: 2, text: 'Another Item'}
]);

var myTable = new TableView({
  collection: list
});

myTable.render();
bernie
  • 9,820
  • 5
  • 62
  • 92