Using Backbone.Marionette
, I would like to render a collection of items along with a header.
I'm aware that Marionette.CollectionView
does not have a template, as it only renders ItemView
s.
I'm currently using Marionette.LayoutView
, but have to define an extra DOM element for the 'list' region.
Is there any other way to do this? Possibly without the extra DOM element?
Maybe I could change open()
for this particular region?
Current Result:
<div class='collection'>
<h3>Featured</h3>
<div class="list"></div>
</div>
Desired Result:
<div class='collection'>
<h3>List Name</h3>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
Render Code:
var col = new LCollection([{name: "foo"}, {name: "bar"}]); // Defined earlier, not relevant here
var list = new ListView({collection: col});
var layout = new MyLayout({model: new Backbone.Model({name: "Featured"})});
app.featured.show(layout);
layout.list.show(list);
Views:
var ListItemView = Backbone.Marionette.ItemView.extend({
template: '#list-item',
tagName: 'li'
});
var LessonListView = Backbone.Marionette.CollectionView.extend({
tagName: 'ul',
itemView: ListItemView
});
var MyLayout = Backbone.Marionette.Layout.extend({
template: "list-layout",
regions: {
list: '.list'
}
});
Templates:
<script type="text/template" id="list-item">
<%= name %>
</script>
<script type="text/template" id="list-layout">
<h3><%= name %></h3>
<div class="list"></div>
</script>
https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.compositeview.md
Applied for you :
Templates
<script id="list-item" type="text/html">
<%= name %>
</script>
<script id="list-layout" type="text/html">
<div class='collection'>
<h3><%= name %></h3>
<ul></ul>
</div>
</script>
JS
RowView = Backbone.Marionette.ItemView.extend({
tagName: "li",
template: "#list-item"
});
TableView = Backbone.Marionette.CompositeView.extend({
itemView: RowView,
// specify a jQuery selector to put the itemView instances in to
itemViewContainer: "ul",
template: "#list-layout"
});
Marionette 3 doesn't use CompositeView
any more, so if we want to get something like this:
<div class='collection'>
<h3>List Name</h3>
<ul>
<li>FOO - BAR</li>
<li>FOO - BAR</li>
<li>FOO - BAR</li>
...
</ul>
</div>
We have to use CollectionView
& View
with regions.
We are going to define two templates, a first one that is the 'parent' and another one for each 'child' that the parent has.
<div class='collection'>
<h3>List Name</h3>
<ul></ul>
</div>
<p>Item <%= value%></p>
Lets define a default model and its collection to fill the list.
const Item = Backbone.Model.extend({});
const Items = Backbone.Collection.extend({
model: Item
});
First, we have to create a View
for our child representation, so:
import ItemViewTemplate from './childTemplate.html';
const ItemChildView = Marionette.View.extend({
template: _.template(ItemViewTemplate),
className: 'item-child-view',
tagName: 'li' // <-- The element where we will wrap our item template (it is not defined in the HTML file)
});
Second, we have to create a CollectionView
that manages each child, so:
const ItemsCollectionView = Marionette.CollectionView.extend({
tagName: 'ul', // <-- The element where we will wrap our collection of items (it is already in the parent HTML file)
childView: ItemChildView,
className: 'items-collection-view'
});
Finally, we have to create the main View
, that contains the parentTemplate.html and in this one we define the region where we will load the collection of elements, so:
import ItemsViewTemplate './parentTemplate.html';
const ItemsView = Marionette.View.extend({
tagName: 'div',
className: 'items-view',
template: _.template(ItemsViewTemplate),
regions: {
body: {
el: 'ul', // <-- This is the HTML tag where we want to load our CollectionView
replaceElement: true // <-- With this option, we overwrite the HTML tag with our CollectionView tag
}
}
});
Now we create the instances needed to make this works:
const app = new Marionette.Application({
region: '#main'
});
// Three simple Items
let item1 = new Item({value: 1});
let item2 = new Item({value: 2});
let item3 = new Item({value: 3});
// Put this Items into a Collection of Items
let items = new Items([item1, item2, item3]);
// Create the main View
let itemsView = new ItemsView();
app.showView(itemsView);
// Create the CollectionView for the Items
let itemsCollectionView = new ItemsCollectionView({
collection: items
});
// Load the CollectionView of Items into the region that we specified in the main View
itemsView.showChildView('body', itemsCollectionView);
app.start();
If we run this, we get:
<div class="collection">
<h3>List Name</h3>
<ul class="items-collection-view">
<li class="item-child-view"><p>Item1</p></li>
<li class="item-child-view"><p>Item2</p></li>
<li class="item-child-view"><p>Item3</p></li>
</ul>
</div>
Hope it helps! Reference
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With