0
votes

I'm using Marionette for a while, but I'm not sure how I can do what I want, in a simple manner.

I have a composite view, which renders something like this:

<div class="row">
  <div class="col-xs-12">
    <div id="items"></div>
  </div>
</div>

Each of my item is being rendered as a:

<div class="col-xs-3">foo</div>

The problem here is, is that every 4 items, I want to render a new row, so things are pretty and do not screw up bootstrap's grid spacing.

In sum, if I just render them as they are, this will happen:

<div class="row">
  <div class="col-xs-12">
    <div id="items">
       <div class="col-xs-3">foo</div>
       <div class="col-xs-3">foo</div>
       <div class="col-xs-3">foo</div>
       <div class="col-xs-3">foo</div>
       <div class="col-xs-3">foo</div>
       <div class="col-xs-3">foo</div>
       <div class="col-xs-3">foo</div>
       <div class="col-xs-3">foo</div>
    </div>
  </div>
</div>

As you can see, this breaks up bootstrap, because we have a lot more then 12 grid space in those item divs.

What I want is:

<div class="row">
  <div class="col-xs-12">
    <div id="items">
       <div class="col-xs-3">foo</div>
       <div class="col-xs-3">foo</div>
       <div class="col-xs-3">foo</div>
       <div class="col-xs-3">foo</div>
    </div>
  </div>
</div>
<div class="row">
  <div class="col-xs-12">
    <div id="items">
       <div class="col-xs-3">foo</div>
       <div class="col-xs-3">foo</div>
       <div class="col-xs-3">foo</div>
       <div class="col-xs-3">foo</div>
    </div>
  </div>
</div>

What is an wasy way to achieve that effect? I should have a view for rows, and view for a collection of rows and a view for each item? That just seems too much trouble.

2
It really depends on the desired effect, but if you give a min-height to the col-xs-3 elements, you should not need any extra row wrapper, as they will gracefully overflow to a new line. Otherwise you need a collection of simple CollectionViewss, which does not seem a big drama either.moonwave99

2 Answers

1
votes

You can exploit Collection/CompositeView's childViewOptions which accepts a function. From the CompositeView you can pass the template you need. So for example:

childViewOptions: function () {
   var template = defaultTemplate;
   if (++this.childCount % 4 == 0) 
      // 3 children have been rendered, this one is the 4th
      template = fourthTemplate;
   return {
      template: template
   } 
}

where this.childCount is a property of your CompositeView, and should be initialized somewhere.

initialize: function () {
   this.childCount = 0;
}

If you're loath to pollute your view with extra props, you can count the number of children with Marionette's hard dep Babysitter, which manages a Collection/CompositeView's children:

childViewOptions: function () {
   var template = defaultTemplate;
   if ((this.children.length + 1) % 4 == 0) 
      // 3 children have been rendered, this one is the 4th
      template = fourthTemplate;
   return {
      template: template
   } 
}
1
votes

I'd say override attachHtml to achieve this. It gets called with the current view, the child view being attached and the index that view has in the collection.

You'd have to look at the index and figure out when to add a new bootstrap row and then make sure you insert the new child into the correct row.

Make sure you understand how the default implementation of attachHtml deals with buffering before you write your own.