Reputation: 10585
I am writing my first Marionette
app and would like to use the Marionette
UI structure.
My understanding is that, roughly speaking,
Region
is 1:1 with an existing, single DOM node (like a div
or a span
) and may contain View
s, including the special ones provided by Marionette
Layout
is a View
as well as a container of Region
s and specifies a template
by which those regions will be arranged; as a View
it may be rendered into a Region
So I think this means you must follow this sort of hierarchy:
- Root (region) [could be more than one]
-- Layout A
--- Inner Region A1
--- Inner Region A2
-- Layout B
--- Inner Region B1
--- Inner Region B2
-- View C
--- maybe some subviews?
If my assumptions are wrong, please correct.
In any case, my application has a navigation and content area in the UI. Now, when the script is loaded, we may be loading it into a page that already has div#region-navigation
in place to customize the appearance, or we may be loading it into a page without the node in place. If the navigation node is in place, we don't need to render it, but we do need to be able to maintain a reference to it and do things to it ("Log In" => "Log Out" for instance). On the other hand, if it is not in place, we need to render and maintain it.
My question is: what is the "Marionette" way to handle this? I have thought of one way, but I would really like to avoid going down any unnecessarily painful paths.
My solution is to create an absolute RootRegion
that is a single selector (default body
) that definitely does not exist at the time of creation.
I would have two AppLayout
s: an InjectedAppLayout
, where the layout only has a Content
region, and a ManagedAppLayout
, where the layout replaces the contents of body
.
Then based on the script
tag data-
params and/or what is on the page (using jQuery) I can choose which Layout
to use.
In either case, I have a HeaderRegion
and a ContentRegion
. In the case of an InjectedAppLayout
the HeaderRegion
lives outside while the ManagedAppLayout
contains both. Then, I would possibly need to make a separate ExternalHeaderRegion
and InternalHeaderRegion
or use a conditional because I would need to handle things very differently depending on whether it is being managed by me or not.
This seems very sub-optimal but I haven't found any example of how people manage this.
Finally, in the case of an InjectedAppLayout
, I am afraid that the div
containing the ContentLayout
may be very small even if the screen width is big because I do not control it. My styles, using Bootstrap
and media queries, all use max-width
values to determine which styles to set. My question is: will the @media (max-width: XXXpx)
queries still apply to the containing div
in the case of the injected app layout?
Upvotes: 2
Views: 738
Reputation: 2921
I've used following structure
-Marionette Application (root - have regions hash of existing node elements)
-- LayoutView (breaks application region in sub regions if needed)
---CollectionView || CompositeView (render collections)
----ItemView
||
---LayoutView (create more sub-regions)
---- (other sub views)
||
---ItemView (render model)
+Router and controllers for application statuses maintain
Lets separate responses between this stuff
Application - starts first. In charge of keeping constants and global params, start and stop sub modules load default routers and controllers + provide Request/Response channel.
1) Can receive some extra params on start
var options = {
something: "some value",
another: "#some-selector"
};
MyApp.start(options);
2) have regions has to work with existing nodes (navs, content, footer, sidebars and so on)
MyApp.addRegions({
someRegion: "#some-div",
anotherRegion: "#another-div"
});
So you can provide some params to JS to render correct views + you can hook-up your application with node elements
Router and Controller
Helps you to render correct view according to application status. In charge of keeping application view correct according to the url and provide navigation You can use it with links + navigate manually with navigate method
var MyRouter = new Marionette.AppRouter({
controller: myController,
appRoutes: {
"foo": "doFoo",
"bar/:id": "doBar"
}
});
LayoutView In Charge of rendering and closing subviews. Separate parent node in some child
Backbone.Marionette.LayoutView.extend({
template: "#layout-view-template",
regions: {
menu: "#menu",
content: "#content"
}
});
Using this structure you can pass to application some params to let application know if user loged in or not. According to this you can add regions with addRegions and render some Layouts (like 'UserNav' or 'GuestNav') . Layout will render its child views like UserLinks, UserAvatar and so on. Then user click links Router and Controller handle this and tell Application what to render in some region.
Upvotes: 3