Search code examples
backbone.jscontrollermarionettesingle-page-application

Marionette: how to use multiple controllers in AppRouter?


This would be a repeated question but I'm unable to find any practical answer on how to use multiple controllers in the AppRouter, for example in my code what I'm trying:

define([
'marionette', 
 'apps/contents/workpackage/workpackage_controller',
 'apps/contents/overview/overview_controller',

], function(
Marionette, 
WorkpackageController
OverviewController

) {

return Marionette.AppRouter.extend({
initialize: function(options) {
  this.wpcontroller = new WorkpackageController({region: options.region});
  this.ovcontroller = new OverviewController({region: options.region});
},
appRoutes: {
  'wp1': 'wpcontroller#workPackageContents1', //Workpackage Controller
  'overview': 'ovcontroller #overviewcontent' //Overview Controller
}
});
});

Solution

  • Well, as you probably already know, AppRouter doesn't take multiple controllers. But that doesn't mean that you can't modularize your controller objects. What I mean is that you can concatenate several controller objects together. In this example, note that my controllers are plain objects as per the v2.4.4 spec (see docs). (If you want some Marionette functionality, you can simply use a Marionette.Object on one controller and follow the recipe below.)

    Plain JS Objects

    So, if controller is defined as:

    var workpackageController = {
      workPackageContents1: function () {
        // method logic //
      }
    }
    

    and the other:

    var overviewController = {
      overviewcontent: function () {
        // method logic //
      }
    }
    

    then I'd instantiate my AppRouter like this:

    return Marionette.AppRouter.extend(
      appRoutes: {
        'wp1': 'workPackageContents1', //Workpackage Controller
        'overview': 'overviewcontent' //Overview Controller
      },
      controller: _.extend(workpackageController, overviewController)
    });
    

    I'm using underscore's _.extend() to merge the properties of my controller objects into one object that the Marionette.AppRouter can ingest. This implies that the methods in the independent controllers objects must have unique names or there will be name collisions. That is, you lose the namespacing of the formerly independent objects.

    This may or may not work for you considering that you're still using one controller object. However, it does allow you to declutter your controller object.

    With Marionette.Object

    If you decide to use a Marionette.Object, just change the definition of the first object in _.extend() to:

    var WorkpackageController = Marionette.Object.extend({
      workPackageContents1: function () {
        // method logic //
      }
    })
    

    and your _.extend() will now look like:

    _.extend(new WorkpackageController, overviewController);
    

    where overviewController is still a plain object that you're using to simply add more methods to WorkpackageController.