Reputation: 150624
I have an application that I want to create using Backbone Marionette. Basically, it's UI structure is very simple. There are:
As an example, the menu might switch between two parts of the application, such as "mail", "calendar" and "contacts". Each of those parts has its own sub-navigation which shall be shown in sub-navigation view, and each part has a default view. E.g., in the "mail" part this may be the "inbox" view, in the "calendar" part this may be the "month" view.
So, generally, we have a nested navigation.
How do I implement this using routers?
My idea is to have an application-level router that just provides routes for the parts such as #mail
and #calendar
.
The sub-navigation views then should have their own routers. So, e.g., the mail sub-navigation view could have a router for inbox
and sent
.
In the end I want to have a route such as #mail/inbox
, but the first part should be handled by the top-level router, the second part should be handled by the sub-level router.
My question is whether I can nest routers in a way that the sub-level routers do not need to know the URL prefix such as "mail", and there is a cascading routing happening. Is this possible?
Or is this approach completely wrong?
Upvotes: 2
Views: 1631
Reputation: 35890
I don't know if Marionette has a solution for this, but there's a plugin called Backbone.subroute, which provides the kind of functionality you're looking for.
Separating sub-routes in this way is a legitimate pattern, and I've used it previously. However, I've since come to the conclusion that having each section's "main" route in the main application router was not the way to go, because it separates concerns that should live together. Instead I've started implementing a common base class for routers, which provides for a "root" URL:
var BaseRouter = Backbone.Router.extend({
//Root path for all routes defined by this router. Override this in a deriving
//class for keeping route table DRY.
urlRoot: undefined,
//override the route method to prefix the route URL
route: function(route, name, callback) {
if(this.urlRoot) {
route = (route === '' ? this.urlRoot : this.urlRoot + "/" + route);
}
//define route
Backbone.Router.prototype.route.call(this, route, name, callback);
//also support URLs with trailing slashes
Backbone.Router.prototype.route.call(this, route + "/", name, callback);
}
});
Usage:
var CalendarRouter = BaseRouter.extend({
//all routes will be relative to "calendar"
urlRoot:"calendar",
routes: {
//...
}
}):
Granted, for my case this makes sense also because I define other common router tasks in the base class. Just to avoid typing the extra "calendar" prefix for each route url doesn't really warrant it.
Edit: Just to clarify, the Backbone.SubRoute plugin doesn't force you to define the root route in the main router, you can use it in the same way as the base class I suggested. But if all you want is a route prefix, then the base class is a lighter, simpler solution.
Upvotes: 2