0

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.

George Silva
  • 3,454
  • 10
  • 39
  • 64
  • 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 `CollectionViews`s, which does not seem a big drama either. – moonwave99 Jun 16 '15 at 07:30

2 Answers2

1

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.

ivarni
  • 17,658
  • 17
  • 76
  • 92
1

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
   } 
}
seebiscuit
  • 4,905
  • 5
  • 31
  • 47
  • I'm curious how you applied this Answer. I admit that I only scanned your question when I wrote this up and then realized that this only works to switch templates on a `childView` but not to modify the `CompositeView` template. – seebiscuit Jun 18 '15 at 14:50
  • this will not work for the original question, but instead of rendering a bunch of rows, I used this technique to render a carousel, with the proper active css property. Thanks! – George Silva Jul 15 '15 at 18:35