4
votes

I am having an application layout like the one attached. The upper panel is already to the page (i.e. in the server's HTML response). While the user interacts with the elements in that panel the content of the dynamic panel below changes accordingly.

I've studied Backbone Marionette various View types and Region Manager. But I still can't figure out a way to implement this. I need to capture events from the already rendered elements and change the dynamic content accordingly. As I understand, every time a region is created to show a specific Marionette view, the region's content is replaced by that view's el. And with that I cannot have a Layout view for the container of the whole thing.

So can this be done in anyway using Marionette?

Sample Layout

2
Well in a Layout View you could set multiple regions inside of the view, so you can assign your menu and your content to two different regions and let the Layout View mediate events between them.Ingro
One way to approach this is to create a controller (could be a Backbone.View serving as a "master" view on the page. Then you can attach a view to the panel (hopefully you have a class or id at the topmost container of the panel that you could designate as the panel's el). From there, you can capture the clicks or changes on the elements in the panel, then trigger custom events up to the master. The master would then "choose" which dynamic view to display. This is kind of a strategy pattern approach.Brendan Delumpa

2 Answers

3
votes

You can certainly support what I would call a "pre rendered" or partial view. In fact, here's a Marionette View that I use quite a bit, as I'm working under with an app that includes server side partial views:

My.PartialView = Backbone.Marionette.Layout.extend({
   render: function () {
      //noop
      if (this.onRender) {
         this.onRender();
      }
      return this;
   },
   onShow: function () {
       // make sure events are ready
       this.delegateEvents();
   }
});

It's simple to use:

My.NavBar = My.PartialView.extend({
    events: {
        "change #search-input": "searchRequested",
        "click #faq-link": "faqRequested",
        "click #home-link": "homeRequested",
    },
    searchRequested: function (e) {
        // search
    },
    faqRequested: function (e) {
        // show the faq
    },
    homeRequested:function () {
        // go home
    }
});

var navbar = new main.views.NavBar({ el: ".my-nav" });
someRegion.show();
// or, just wire up the events manually
navbar.delegateEvents();
1
votes

I think the better way is using constructor. Make your rendered layout class.

App.RenderedLayout = Marionette.Layout.extend({
    render: function () {
        if (this.onRender) {
            this.onRender();
        }
        return this;
    },
    constructor: function(){
        this._ensureElement();
        this.bindUIElements();
        Marionette.Layout.prototype.constructor.apply(this, slice(arguments));
    }
});

Then you can use full of Marionette capabilities.

App.module('Some.Page', function (Mod, App, Backbone, Marionette, $, _) {

    Mod.SomeLayout = App.RenderedLayout.extend({
        el: '#renderedDiv',
        events: {
            'click .something': 'onSomethingClick'
        },
        regions: {
            'innerRegion': '#innerRegion'
        },
        ui: {
            something: '.something div'
        },
        initialize: function () {

        },
        onSomethingClick: function(e){
            return false;
        }
    });

    Mod.addInitializer(function(){
        App.addRegions({renderedRegion: '#renderedDiv'});
        Mod.someLayout = new Mod.SomeLayout();
        App.renderedRegion.attachView(Mod.someLayout);
    });

});