Search code examples
javascriptbackbone.jsurl-routingmarionette

processAppRoutes for Maionette AppRouter isn't a function


In my application, I have a global trigger which calls navigate on the router, it basically allows me to write normal links and trigger the backbone routing methods.

Anyway, I'm trying to break up my routers into smaller router objects and then combine them into one main router, on which I can trigger the navigate method without needing to know which sub-router I'm trying to talk to.

I've created some controllers and am trying to pass them in to my AppRouter object using the processAppRoutes method described here, but I keep getting the message that it's not a function. I've checked that my versions are up to date, and I can see the method definition in the source code, but I can't seem to call it.

I'm using requirejs, so I'll post en example of how I've structured my attempt, reduced to the relevant parts for brevity.

users.controller.js:

return Marionette.Controller.extend({
    routes: {
        'users/login': 'login'
    },

    login: function(){
        ...
    }
});

routes.js:

var UsersController = require('users.controller');

var router = new Marionette.AppRouter.extend();
router.processAppRoutes(UsersController, UsersController.routes);

I included the routes as an object of the controller to make them available when returning the controller using requirejs, so that's why that's there.

Basically, my question is this: How can I define routers as separate objects, then combine them into a single router for the whole application?


Solution

  • Here's what I ended up doing:

    routes/routes.js: (Returns an AppRouter object which can then be run as the only AppRouter in the Marionette app)

    var Controllers = {
        Events: require('events/events.controller'),
        Users: require('users/users.controller')
    };
    
    var routes = {};
    var MyAppController = {};
    $.each(Controllers, function(key, controller){
        var c = new controller();
        routes = _.extend(routes, c.routes);
        MyAppController = _.extend(MyAppController, c);
    });
    
    var MyAppRouter = Marionette.AppRouter.extend({
        controller: MyAppController,
        appRoutes: routes       
    });
    return MyAppRouter;
    

    events/events.controller.js: (Just a snippet)

    var EventsController = Marionette.Controller.extend({
        routes: {
            '': 'showEvents',
            'events/add': 'addEvents'
        },
    
        showEvents: function(){ ... },
        addEvents: function(){ ... }
    });
    

    It turns out that I could only run processAppRoutes() on the AppRouter before it had been instantiated with new, and only once. By defining a routes object inside the controller, which isn't used by the controller, I can access it in the routes.js file and iterate through the routes and methods to create an AppRouter object with all the routes for the entire app. Adding a new controller is as easy as requiring it inside the Controllers object.