Reputation: 6907
I am currently building a complex marionette application and have been follow a great book as a reference. However, I am a sucker for reusable code and like to keep things flexible as possible.
My application has various screens and modules, one of which is a dashboard. The dashboard has its own set of responsibilities, so I made the conclusion that it should be a sub-app.
The dashboard is split 50/50 and there are two components inside. I have identified that each of these components (lets say compA
and compB
) each have their own set of responsibilities aswell and should be their own sub apps. However, I will have the use case where compA
will be used in another area of the application.
My first thought with re-use in mind was to simply re-use the views and create a new module where ever this particular view was needed. However, the unique events and actions that come with this view are stored in the controller and API to interact with the module.
So I have ended up with the following structure:
application.js
apps
--dashboard
--compA
--compB
and I have implemented something like the following to reuse functionality from compA
Controller = {
getView: function () {
return new Show.MyView();
}
}
API = {
getMyView: function () {
return Controller.getView();
}
}
App.reqres.setHandler('compa:get:view', function () {
return API.getMyView();
});
Doing this allows me to request a new instance of the view to display and keep the same action logic. However, this means that there is no separation between each section (compA
in the dashboard, and compa
in another section of the app). So if I were to stop the compa
module it would not have the desired results.
Is there a better approach to re-usable modules with minimal duplication of code?
My thought was to extract the Controller logic into a controller object that I can extend, and then creating a new 'sub app' when I would like to re-use the features.
application.js
apps
--dashboard
--compA-dashboard // new instance of Controller
--compA-somewhereelse // new instance of Controller
--compB
It seems as though I may be over-complicating my design pattern.
Upvotes: 1
Views: 1058
Reputation: 24815
Allow me to rename your "component" as "widget" at first. In my opinion "component" is better for things more general than the widgets in your case.
I would arrange those widgets as following:
app.js
/app
/dashboard
/show
show_controller.js
dashboard_app.js
/other
/components
/widgets
/widgetA
widgetController.js
widgetView.js
/widgetB
Since widgetA is dependent from dashboard and is supposed to be use elsewhere, it should be fully decoupled from dashboard.
The 'show' View of Dashboard should have a Layout to define where to show widgetA and widgetB.
Then, in your DashBoardApp, set an appRoute to respond to some route, and then call the controller.
The controller will initialize the Layout.
The Layout will ask for show of RegionA and RegionB.
Listen to 'show' events of RegionA and RegionB, to ask for an App wide request
this.listenTo(regionA, 'show', function(){
App.request 'widget:a:show'
});
Then in Widget module, respond to the App events and deliver the view
App.reqres.setHandler('widget:a:show, function(){
API.getWidgetAView();
});
The later part of my answer is a bit vague with less code. The basic idea is, DashBoardApp should finish his job by sending App request. And then it's components job to deliver the view upon App request, which is fully decoupled.
Upvotes: 1