最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Backbone.Marionette: Add header to collection view - Stack Overflow

programmeradmin5浏览0评论

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 ItemViews.

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>

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 ItemViews.

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>
Share Improve this question edited Aug 1, 2013 at 12:19 Will M asked Aug 1, 2013 at 3:15 Will MWill M 2,1454 gold badges22 silver badges32 bronze badges 1
  • Why not a CompositeView? – steveax Commented Aug 1, 2013 at 3:37
Add a ment  | 

3 Answers 3

Reset to default 14

https://github./marionettejs/backbone.marionette/blob/master/docs/marionette.positeview.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.

1 - Templates

We are going to define two templates, a first one that is the 'parent' and another one for each 'child' that the parent has.

parentTemplate.html

<div class='collection'>
    <h3>List Name</h3>
    <ul></ul>
</div>

childTemplate.html

<p>Item <%= value%></p>

2 - Backbone Model and Collection

Lets define a default model and its collection to fill the list.

const Item = Backbone.Model.extend({});
const Items = Backbone.Collection.extend({
    model: Item
});

3 - Views

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
        }
    }
});

4- Rest of the Code

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();

5- Result

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

I believe the solution above will render the li element directly under the containing div or other region specified, unless you also specify

tagName: "ul"

Then it renders the li elements within a ul element within the specified region.

发布评论

评论列表(0)

  1. 暂无评论