Chapter 9: AppRouter

Assuming you’ve used Backbone prior to reading this book — this entire book assumes you have, even if I myself wouldn’t — you should be familiar with Backbone.Router. Routers are great things that allow single page applications to have multiple URLs as if they were applications spanning multiple pages. This grants users the ability to use the Back and Forward buttons in the browser to navigate around apparent pages of your application that they have seen before, or even bookmark a particular place in your application.

Every good application with more than one screen should take advantage of a router to provide these expected pieces of the user experience. So, let’s get started using Backbone.Router, right? Nah, I have a better idea: let’s use Marionette.AppRouter.

The AppRouter is exactly the same as Backbone’s Router — in fact it extends Router and you can just replace all instances of Router with AppRouter and your application will continue to work exactly the same way — except that it has an additional feature that allows you to use the router in a better way. In chapter 1, I mentioned that people often used their router as the central application namespace object, which is outside the responsibilities of a router. Well, apparently, the router comes under lots of misuse — though this time it isn’t our fault.

Using A Controller

Backbone’s Router was designed to handle the full processing of all of the routes within itself, but if you’ve ever looked at a router on the server, it is little more than configuration used to delegate actions to controllers based on the URL. AppRouter is set up more like a back-end router: it allows you to configure it with a controller, and then respond to a URL change by calling a method on the controller rather than on the router itself.

This keeps the concerns of determining a URL change and parsing it separate from controlling the application based on those changes. In other words: let the router route and the controller control.

Derick has an interesting example in a blog post1 that demonstrates why he created the AppRouter. When he was using Backbone’s Router, his code looked similar to this:

var MyRouter = Backbone.Router.extend({
    routes: {
        "": "main",
        "/category/:catid": "category",
        "/item/:itemid": "item"
    },

    main: function() {
        App.showMain();
    },
    category: function(catid) {
        App.showCategory(catid);
    },
    item: function(itemid) {
        App.showItem(itemid);
    }
});

This is not the same example he gave, but it’s very similar — it’s really just a simplified and generalized version of his code. With some inspiration from Marionette users’ feedback, he decided that instead of just passing requests through to the application manually, he would create a means for himself to add the application as a controller that the router calls methods on directly. Thus AppRouter was born. And hence the name “AppRouter” instead of something like “ControllerRouter”. Obviously, you don’t need to use your application object as the controller, but if you’re using the application object in the same way as Derick was, it’s not a bad choice.

I prefer to use a separate object as the controller, but as long as you’re removing the responsibility of controlling models and views from the router, you’re taking good steps toward better structure.

So, how do we add that controller to an AppRouter? There are two ways to do it: when extending the AppRouter, or when instantiating one. No matter which method you choose to use, you do it by specifying a controller property that points to the object you want to use as the controller.

var MyRouter = Marionette.AppRouter.extend({
    controller: App, // when extending
    ...

});

router = new MyRouter({controller: App}); // when initializing

Note that no AppRouter can use more than one controller object.

Routing To The Controller

Of course, it doesn’t do us any good to assign a controller to the router if we don’t know how to make the router use the controller. Backbone’s Router uses the routes property to specify the routes and map methods to them, which you can also do with AppRouter:

var MyRouter = Marionette.AppRouter({
    routes: {
        "": "index",
        ...

    },

    index: function() {
        ...

    },
    ...

});

This is why you can just replace your old routers with AppRouter and not have any changes. But if you want to map routes to methods on the controller, you use the appRoutes property:

var MyRouter = Marionette.AppRouter.extend({
    controller: App,
    appRoutes: {
        "": "index",
        ...

    },
    ...

});

The syntax is exactly the same. The only difference is that the method name refers to a method on the controller, rather than a method on the router. You can use both routes and appRoutes in the same router, so the routes specified in routes will use methods on the router, while the routes specified in appRoutes will use methods on the controller. It’s important to note that if you have a route that appears in both routes and appRoutes, the appRoutes route will take precedence and the one in routes will never be called.

If you’d like to add routes dynamically after the router is initialized, you can use the appRoute method. It works in exactly the same way as the route method on Backbone’s Routers, except of course that it adds a route that uses the method on the controller rather than on the router. When using appRoute (or just route), you need to pass in two arguments: the route as a string; and the name of the method on the controller that you want to call when the URL matches that route. This is also sent in a string.

router.appRoute('/list/', 'showList');

There are alternative syntaxes for route and appRoute where you can specify a callback function instead of using a method on the router or controller, but I won’t show you those. The use cases are few and far between and aren’t very good practice. If you want to learn more about that syntax, take a look at Backbone’s documention for the route method2.

Summary

If you’re using a router in your web applications, then Marionette’s AppRouter is a very good choice. Even if you’re already using Backbone’s Router, you can just switch them all up for AppRouter without any issues, and you’ll be set for the future when or if your application grows to the point where you need better organization and structure. If you’re just starting your application, there’s no good reason not to use the AppRouter over Router.

It may only be a small step up from the Router, but it can have a noticeable impact on the way you write your code and keep your routers clean.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset