0

I'm trying to preserve the full markup of a template, including the class on the root node when using a marionette region. I'm also trying to avoid creating an extra wrapping div. I've solved the problem, but in a way which I don't think is satisfactory.

I am creating and rendering a layout like this:

MyApp = new Backbone.Marionette.Application();
MyApp.addRegions({
    mainRegion: "#main"
});

AppLayout = Backbone.Marionette.Layout.extend({
    template: '
        <div class="row">
            <div class="col-md-8"></div>
            <div class="col-md-4"></div>
        </div>
    '
});
var layout = new AppLayout();

MyApp.mainRegion.show(layout);

layout.show(new MenuView());

And the result is that my template is rendered like this:

<div id="main">
    <div>
        <div class="col-md-8"></div>
        <div class="col-md-4"></div>
    </div>
</div>

Notice, the class="row" is missing from the root node of the template. It appears that marionette is removing the root div from my template, and then wrapping the contents in a new div.

I have managed to hack a solution to this like this

AppLayout = Backbone.Marionette.Layout.extend({
    template: '
        <div><!-- sacrificial div -->
            <div class="row">
                <div class="col-md-8"></div>
                <div class="col-md-4"></div>
            </div>
        </div>
    ',
    onRender: function () {
        // get rid of that pesky wrapping-div
        // assumes 1 child element.
        this.$el = this.$el.children();
        this.setElement(this.$el);
    }
});

I'm adding an extra root div (my sacrificial div) to my template which marionette removes, and then I'm telling marionette to use the first child as the layouts 'el' (as per Turning off div wrap for Backbone.Marionette.ItemView).

This seems crazy!

Can somebody suggest a better way?

EDIT: n.b. I'd like to keep all the template logic in the template, so don't want to have to use code in my view to specify the class on the root node - if I do this, I end up with a maintenance headache.

Community
  • 1
  • 1
xanld
  • 977
  • 1
  • 11
  • 22

3 Answers3

2

Try with

AppLayout = Backbone.Marionette.Layout.extend({
    template: '
            <div class="col-md-8"></div>
            <div class="col-md-4"></div>
    ',
    className: "row"
});
David Sulc
  • 25,946
  • 3
  • 52
  • 54
  • That'd do it! The only thing is that I don't want to add display logic ('i.e. the classname') into my view object. I'd rather keep it in the template. I think I prefer my current solution for this reason... – xanld Nov 07 '13 at 06:57
  • (so I'm still on the lookout for a proper solution...) – xanld Nov 10 '13 at 04:17
0

AppLayout is missing its region(s).

AppLayout = Backbone.Marionette.Layout.extend({
    template: '
        <div class="row">
            <div id="region1" class="col-md-8"></div>
            <div id="region2" class="col-md-4"></div>
        </div>
    ',
    regions: {
        region1: '#region1',
        region2: '#region2'
    }

});

Then at your instantiated layout:

layout.region1.show(new MenuView()); 
layout.region2.show(new MenuView()); 
Cheng Ping Onn
  • 687
  • 1
  • 8
  • 17
0

Instead of assigning the template to a string, compile the HTML into a template function with underscore. Something like this:

template: _.template(
  '<div class="row">' +
    '<div class="col-md-8"></div>' +
    '<div class="col-md-4"></div>' +
  '</div>'
)
Craig J
  • 369
  • 2
  • 10
  • I don't think this makes any difference does it? – xanld Nov 07 '13 at 07:02
  • Yes, it will preserve the `
    ` element. See http://jsfiddle.net/craigjennings11/gLykP/ for an example.
    – Craig J Nov 07 '13 at 22:09
  • Hi, thanks for your answer. Am I missing something though, the jsfiddle doesn't appear to have a class of row surrounding the two column divs, and the background is not gray... – xanld Nov 10 '13 at 04:16
  • Did you uncomment the `//_.template` statement and run it again? – Craig J Nov 11 '13 at 16:59