Regex routing with Backbone.js
- 12/9/2011
- ·
- #index
Routing is an application’s way of saying, “there would be something good at that URL, but since it’s hard to store things there I’ll just put it somewhere else and pretend you don’t notice.” It’s a hack, yes, but it’s also an easy system for turning abstract database identifiers into human-friendly URLs.
Most application frameworks have a single preferred format for their routing table that typically looks something like this:
$routes = array(
'get /index' => 'viewIndex',
'get /single/:id' => 'viewSingle'
);
Backbone.js is no exception. By default, Backbone routes are limited to matching any slash-delimited URL fragment (“parameters”, denoted by a colon) and wildcard matches (“splats”, denoted by an asterisk). For the example above, the table in a Backbone router would be:
routes: {
'index': 'viewIndex',
'single/:id': 'viewSingle'
},
But what if you want to be more selective in your routing, and only route URL fragments that match a certain criteria? The obvious answer is to use a regular expression. Backbone supports this, indeed, all routes are converted into test-able RegExp
objects as they’re added to the routing table. But Backbone’s Router.route
method only supports adding such routes one at a time. That works fine as long as you only have a single route, or if you aren’t concerned about maintaining an exhaustive list of one-off routes–both rare cases for larger applications.
Fortunately, there’s an easy solution: set up an array of regular expression routes, then run Router.route
on each route in the table.
Say you want to separate routes for lower-case names like “salmon”, “halibut”, or “sole” into those that belong with a specific letter. A few simple regex routes can handle this easily. Check it out:
var FishRouter = Backbone.Router.extend({
// we'll define routes in a moment
routes: {},
// set up routing table
initialize: function() {
var router = this,
routes = [
[ /^fish\/([a-z] )$/, 'getUntastyFish', this.untastyFish ],
[ /^fish\/(s[a-z] )$/, 'getTastyFish', this.tastyFish ],
[ 'how-to-fish', 'getAllFish', this.fishHowTo ]
];
_.each(routes, function(route) {
router.route.apply(router,route);
// ^ Say it ten times fast
});
},
// a handler for tasty fish
tastyFish: function (name) {
alert('Mmm...tasty ' name '!');
},
// a handler for not-so-tasty fish
untastyFish: function (name) {
alert('That ' name ' wasn\'t very tasty...');
},
// a handler for instructions
fishHowTo: function () {
alert('Choose a delicious fish from the list below.\n\n (hint: the tastiest fish start with \'s\')');
}
});
// initialize the router
new FishRouter();
// call Backbone.history.start() to handle initial routing
Backbone.history.start();
Voila–a RegEx-enhanced routing table for Backbone.js. Call Backbone.History.start()
and away you go!
Demonstration
Updated 03. Apr 2012 to reflect demonstration code