Reputation: 51
I'm having some trouble getting my head around the correct way to do recursion in Marionette. I've seen answers to some other questions but I've broken this down into an extremely simple example at http://jsfiddle.net/vZY2v/. I know the secret is in the use of composites but I haven't hit on the right way to do it.
I want to produce N-level embedded lists such as:
<ul>
<li>Bob</li>
<ul>
<li>Jim</li>
<li>Jane</li>
</ul>
</ul>
The HTML looks like:
<body>
<div id='myContainer'></div>
<script type='text/template' id='my-item'>
<%= name %>
</script>
</body>
Here's the code:
var jsonData = [{
name: 'Bob',
children: [{
name: 'Jim'
}, {
name: 'Jane'
}]
}, {
name: 'Sally',
children: [{
name: 'Sue',
children: [{
name: 'John'
}, {
name: 'Lisa'
}]
}]
}];
var Item = Backbone.Model.extend({});
var ItemCollection = Backbone.Collection.extend({
model: Item
});
var i = new Item();
var Manager = new Marionette.Application();
Manager.addRegions({
mainRegion: "#myContainer"
});
var RecursiveView = Marionette.CompositeView.extend({
tagName: "li",
template: '#my-item',
initialize: function () {
if (this.model.get('children')) {
this.collection = new ItemCollection(this.model.get('children'));
}
}
});
var MotherView = Marionette.CollectionView.extend({
tagName: "ul",
itemView: RecursiveView
});
var myColl = new ItemCollection(jsonData);
var x = new MotherView({
collection: myColl
});
Manager.mainRegion.show(x);
The desired output is like below:
Upvotes: 0
Views: 264
Reputation: 1041
You absolutely shouldn't need to override the appendHtml method like that - this is basically what the CompositeView is designed for.
I've updated your fiddle: http://jsfiddle.net/vZY2v/1/
Yes, it has an extra root node, but you can easily make your root node have a different template, that doesn't render an li
, or the name property.
The main difference is the use of itemViewContainer
to let Marionette insert the ItemViews in the appropriate place for you, rather than doing it yourself.
Upvotes: 1
Reputation: 51
I think I can answer my own question here with an updated example at http://jsfiddle.net/nDfCT/1/.
The secret was moving the LI tag into the template and rendering RecursiveView with a instead, and adding an appendHtml function like this:
var RecursiveView = Marionette.CompositeView.extend({
tagName: "ul",
template: '#my-item',
initialize: function () {
this.collection = this.model.children;
},
appendHtml: function (collectionView, itemView) {
collectionView.$('li:first').append(itemView.el);
}
});
Upvotes: 1