How to achieve deprecated CompositeView functionality in Marionette 3+?
Asked Answered
S

1

7

As stated in the latest Marionette docs:

CompositeView is deprecated. You should use the replaceElement option on Region.show and render a CollectionView into a region inside a View to achieve this functionality.

I still can't understand how CompositeView functionality should be achieved now.

Previously, CompositeView was perfect for using with such template:

<script id="table-template" type="text/html">
<table>
  <% if (items.length) { %>
  <thead>
    <tr>
      <th>ID</th>
      <th>Name</th>
      <th>Description</th>
    </tr>
  </thead>
 <% } %>

  <tbody></tbody>

  <tfoot>
    <tr>
      <td colspan="3">some footer information</td>
    </tr>
  </tfoot>
</table>

new MyCompositeView({
  template: "#table-template",
  templateContext: function() {
    return { items: this.collection.toJSON() };
  }
  // ... other options
});

If we decide to use LayoutView instead of CompositeView then we need to code manually a lot of event bindings (for example to show / hide table header based on number of items in collection). This makes things harder.

Are there any clean and not complicated ways to live without CompositeView?


Thank you for any help or advice.

Septuagesima answered 31/3, 2016 at 19:21 Comment(0)
P
3

It looks like Marionette 3 is going to get rid of some concepts to make the framework simpler overall, and easier to understand.

Marionette.View in 3 is going to include functionality from what was ItemView and LayoutView. CompositeView is deprecated in favour of just using RegionManager, which is now included into View.

v2 --> v3
View -> AbstractView  
ItemView, LayoutView -> View

Here's a quick example app:

var color_data = [ { title:'red' }, { title:'green' }, { title:'blue' } ];

var Color = Backbone.Model.extend({
  defaults: { title: '' }
});

var Colors = Backbone.Collection.extend({
  model: Color
});

var ColorView = Mn.View.extend({
  tagName: 'tr',
  template: '#colorTpl'
});

var ColorsView = Mn.CollectionView.extend({
  tagName: 'tbody',
  childView: ColorView
});

var AppView = Mn.View.extend({
  template: '#appTpl',
  templateContext: function(){
    return {
      items: this.collection.toJSON()
    };
  },
  ui: {
    input: '.input'
  },
  regions: {
    list: {
      selector: 'tbody',
      replaceElement: true
    },
  },
  onRender: function(){
    this.getRegion('list').show(new ColorsView({
      collection: this.collection
    }));
  },
  events: {
    'submit form': 'onSubmit'
  },
  onSubmit: function(e){
    e.preventDefault();
    this.collection.add({
      title: this.ui.input.val()
    });
    this.ui.input.val('');
  }
});

var appView = new AppView({
  collection: new Colors(color_data)
});
appView.render().$el.appendTo(document.body);
<script src='http://libjs.surge.sh/jquery2.2.2-underscore1.8.3-backbone1.3.2-radio1.0.4-babysitter0.1.11-marionette3rc1.js'></script>

<script id="colorTpl" type="text/template">
  <td><%=title%></td>
  <td style="background-color:<%=title%>">&nbsp;</td>
</script>

<script id="appTpl" type="text/template">
<table width="100%">
  <% if(items.length) { %>
    <thead>
      <tr>
        <th width="1%">Title</th>
        <th>Color</th>
      </tr>
    </thead>
  <% } %>
  <tbody></tbody>
  <tfoot>
    <tr>
      <td colspan="2">
        <form><input type="text" class="input" autofocus><input type="submit" value="Add Color"></form>
      </td>
    </tr>
  </tfoot>
</table>

  
</script>
Pinnatipartite answered 2/4, 2016 at 16:26 Comment(5)
Great, thank you a lot for amazing example! It solves the issue.Septuagesima
Finally I discovered that there is no such option replaceElement: true in Marionette. Why are you using it?Septuagesima
Jamesh, we are talking about Marionette v3, and replaceElement option is recommended for use instead of CompositeView. It might not be entirely supported yet, but your statement is incorrect.Pinnatipartite
replaceElement: true is required to achieve behaviour similar to the childViewContainer in CompositeView. Otherwise the region would be a container itself by default, which would be one extra element in your DOM tree. Default region behaviour would make it harder in examples like this one, in a table, which is sensitive to the structure of DOM elements.Pinnatipartite
my apologies. I was thinking replaceElement: true is not available yet in Marionette 3. But that was wrong and your answer is fully correct! Thank you once more.Septuagesima

© 2022 - 2024 — McMap. All rights reserved.