Marionette.js. CollectionView. Build Trees in Marionette 3

As in tables, trees in Marionette 3 require us to combine `View` and `CollectionView` to build up the tree in a more explicit manner than the implicit version provided by Marionette 2.

by marionettejs

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.radio/2.0.0/backbone.radio.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.marionette/3.0.0/backbone.marionette.js"></script>
<script id="node-template" type="text/template">
    <%- nodeName %>
    <% if (nodes.length) { %>
    	<ul></ul>
    <% } %>
</script>

JavaScript

const TreeNode = Mn.View.extend({
  tagName: 'li',
  template: '#node-template',

  regions: {
    tree: {
      el: 'ul',
      replaceElement: true
    }
  },

  onRender() {
  	const nodes = this.model.get('nodes');
    
    //show child nodes if they are present
    if (nodes.length) {
      const treeView = new TreeView({
        collection: new Backbone.Collection(nodes)
      });
      
      this.showChildView('tree', treeView);
    }
  }
});

const TreeView = Mn.CollectionView.extend({
  tagName: 'ul',
  childView: TreeNode
});

const tree = new Backbone.Collection([
  {
    nodeName: 'Parent 1',
    nodes: [
      {nodeName: 'Child 1', nodes: []},
      {nodeName: 'Child 2', nodes: []}
    ],
  },
  {
    nodeName: 'Parent 2',
    nodes: []
  },
]);

const treeView = new TreeView({
  collection: tree
});

treeView.render();
$('body').append(treeView.$el);