Tres
Tres

Reputation: 1495

Backbone.Marionette Layout + Region + View inserts an extra element, breaking Bootstrap styles

I'm running into a problem getting Backbone.Marionette to cooperate with Twitter Bootstrap. Bootstrap expects markup to conform to predefined patterns in order to work, but the way that Backbone and Marionette handle things, it seems to be impossible to use a Marionette.Layout to generate Bootstrap-compliant markup for a navbar with an embedded dropdown.

Here's the problem:

Let's say I have a Marionette.Layout representing the navbar, and I want to have a region, where I will put the CollectionView or CompositeView that manages the items in the dropdown. The region is a selector, so in this case if we have:

<div class="navbar">
  <ul class="nav">
    <li>Static item</li>
    <li id="dynamic-dropdown"></li>
  </ul>
</div>

Then the Layout would specify the region for the dynamic dropdown as follows:

Marionette.Layout.extend({
  regions: {
    dropdown: '#dynamic-dropdown'
  }
...
});

I would then have a CompositeView that takes care of rendering the dropdown item models, specifies the extra markup for the Bootstrap dropdown, and so forth. The problem is that it appears to be impossible to make #dynamic-dropdown be the $el for the CompositeView, as Backbone always inserts an extra div (or whatever you specify in tagName). In order for the dropdown to appear as expected, I need to get rid of that extra element and have the view's root be #dynamic-dropdown.

I've put together a jsfiddle illustrating what I mean.

tl;dr How do I make a View's root element be the region specified in a Marionette.Layout?

Upvotes: 0

Views: 2414

Answers (1)

Amulya Khare
Amulya Khare

Reputation: 7708

You just need to make sure that the markup that is generated in the end follows the same as required by Bootstrap (use the console to debug).

The required markup is as follows:

enter image description here

The markup generated by your code has the following problems:

enter image description here

So, to fix it you have to change your nav template to:

<script type="text/html" id="nav">
  <div class="navbar">
    <ul class="nav" id="dropdown">
    </ul>
  </div>
</script>

And your views to render <li> instead of <div>

var DropdownItem = Marionette.ItemView.extend({
     tagName: 'li',
     template: "#dropdown-item"
});

var DropdownView = Marionette.CompositeView.extend({
    template: "#dropdown-collection",
    className: 'dropdown',
    tagName: 'li',
    itemView: DropdownItem,
    itemViewContainer: '#dropdown-items'
});

Here is the working version: http://jsfiddle.net/7auhR/6/

Upvotes: 4

Related Questions