Dynamically add regions to Marionette layout

2019-03-27 04:48发布

问题:

I have a layout, but cannot define all of its regions in advance because they are not known.

So later on an ItemView is created and I'd like to create a new region in the layout using the view's ID as the region's name so I can then say:

layout.dynamicRegionName.show(newItemView);

But there is cyclic dependency here.

  1. I haven't rendered the view yet, so I cannot make a reference to its DOM element to be used in the layout's call to .addRegion()

  2. I cannot render it, precisely because I want it to get attached to the DOM tree through the dynamically added region by calling its .show()

@DerickBailey In the Marionette.Layout docs in github I believe there is an error in the example that has: layout.show(new MenuView());

but technically this is close to what we'd need here i.e. to be able to do:

layout.addRegion(VAR_WITH_NEW_REGION_NAME, aViewInstance);

and have this add a new Region into the layout rendering inside it directly the view instance.

Am I missing some other obvious way to achieve this? Is that a known missing functionality? Is there a reason not to have it?

I'm aware of this previous Q: "Dynamically add/remove regions to a layout" but don't see any clear/definite answer to it.

回答1:

Marionette v1.0 (v1.0.2 is latest, right now) supports dynamic regions in Layouts.


var MyLayout = Marionette.Layout.extend({
  template: "#some-template"
});

var layout = new MyLayout();
layout.render();

layout.addRegion("someRegion", "#some-element");

layout.someRegion.show(new MyView());


回答2:

In one of my projects, I faced a similar issue. I needed to create a form dynamically, i.e the form would contain different field views that could not be determined prior runtime. I needed the fields to be Marionette views because they had pretty complicated behaviour.

The way I have done it in Marionette 1.4 in CoffeeScript:

  class Module.AdditionalOptionsLayout extends Marionette.Layout
    tagName: 'form'

    initialize: (options = {}) ->
      @_fieldViews = options.fieldViews || []

    onRender: ->
      @_showFields @_fieldViews

    _showFields: (fieldViews) ->
      fieldViews.forEach (fieldView) => @_addRegion().show fieldView

    _addRegion: ->
      regionClass = _.uniqueId('field-region__')
      @$el.append $("<div class=\"#{regionClass}\"></div>")
      @addRegion regionClass, '.' + regionClass

Please, let me know if it needs further explanation or I can clarify this in JS. I am also aware that it is a late answer, however, hope somebody could find it still useful. Also, note - the answer is relevant only for Marionette 1.x