Backbone.js Routers

In what follows, we are going to look at Backbone.js routers. Routers are a great place to start whenever you begin developing a Backbone application (or any application for that matter) because you can figure out what URLs and sections your app will need and add hooks in your code to respond to them. It helps define application structure, much like a flow chart would.

The files for demo and download for the following discussion can be found below if you’d like to follow along…

View Demo Download Files

Backbone.js uses routers to execute certain actions when a user goes to a certain URL within a Backbone application. Backbone applications all use routes that follow a # character in the URL. The # might be familiar to you if you’ve ever used it as a named anchor to link to part of the current document without going to a new URL. This is very prevalent in pages that have tables of content at the top (e.g. like in Wikipedia articles), where the links at the top take you to a place on the same page further down. That’s what’s going to happen with Backbone. We’re going to stay on our same page, but we’re going to set up our JavaScript such that Backbone listens for the user going to these links. When the user clicks on different links within the application, instead of going to a different place on the page, we’ll be executing different portions of JavaScript in our code. That’s how a “client-side JavaScript application” essentially behaves.

So let’s say we have the following HTML page where we’ve loaded up Backbone. Note that we’re also going to want to load Backbone’s dependency library Underscore.js. We also want to load jQuery because jQuery has a really nice on method that is useful for catching events thrown by Backbone. If that last sentence seems little unclear to you at this point, you’ll see what we mean a bit later on..

We’re going to be adding code in the <script> section at the bottom. In a larger scale Backbone application, you’d probably have all of your routers in a separate file called “routers.js” or something like the.

<!DOCTYPE html>
<html>
<head>
<script src="js/jquery.js" type="text/javascript"></script> 
<script src="js/underscore.js" type="text/javascript"></script> 
<script src="js/backbone.js" type="text/javascript"></script> 
</head>
<body>
<script type="text/javascript">
</script>
</body>
</html> 

What we need to do first is define some routes. In the <script> section add the following code…

var Router = Backbone.Router.extend({
  routes: {
    "": "home", // url:event that fires
  }
});
var router = new Router;

What we have done here is create a new router and have given it a routes. The “routes” object follows the following format…

url : Name of event that fires

What does this mean? Well the string on the left is the URL that a user of your application is going to and the string on the right is the name of the event that is fired off when that URL is accessed.

So let’s look at our first example. This “” is a blank string. This means you are going to the root URL of your Backbone.js application. So, for example, if you had a BackboneJS application hosted at http://www.yourwebsite.com/. This event would fire when the user went to http://www.yourwebsite.com/ (the home page with no additional parameters or sub-page locations). The event would not fire if they went to http://www.yourwebsite.com/#/newUser or http://www.yourwebsite.com/#/somethingElse because the strings following the hash character would not be empty.

Next we want to add the following right after the code we added in the previous step…

router.on('route:home', function() {
  alert('We have loaded the home view');
});
Backbone.history.start();

Here we are using the jQuery on method mentioned earlier. Backbone.history.start(); is just a method that backbone uses to say “Start listening for routes.” Before routers will work in Backbone, you have to add this method. Just something to remember.

Now in your brwoser, go to your home URL. If you had this application hosted at http://www.yourwebsite.com/, you’d just go to http://www.yourwebsite.com/. If we do this, you shold see the alert fire meaning we are responding to the event “route:home”.

New Routes

Now let’s add another route so that our code looks like the following…

var Router = Backbone.Router.extend({
  routes: {
    "": "home", // url:event that fires
    "new": "createNew"
  }
});
var router = new Router;

Now in the location where we added the previous “on” method, place the following code below that (but before the Backbone.history.start(); statement) …

router.on('route:createNew', function() {
    alert('We are going to create something new here...')
});

Now in your browser, after your home URL add the the following…

/#/new

Such that your URL will be something like http://www.yourwebsite.com/#/new, if you go to it, you can see that the code in our method fires. What if you go to http://www.yourwebsite.com/#/createSomething. You’ll see that the code does not fire? Backbone has not matched either of the routes we have defined so no code is being executed.

Parameters & Splats

If you’ve ever done web development utilizing dynamic pages of any kind, you know that the content on pages are populated depending on the parameters that get passed in. So, for example, if you had a social profile of some sort, you might have something like http://www.9bitSocialNetwork.com/profile?id=2345&view=all. In that case, the parameters “id” and “view” would be used by the website to determine who’d profile to show and how to show it. You’d have one view that defined the layout and what you’d show in that view would depend on the specific parameters.

Backbone.js applications have the ability for you to pass in parameters as well.

Let’s add yet another route such that our code looks like the following…

var Router = Backbone.Router.extend({
  routes: {
    "": "home", // url:event that fires
    "new": "createNew"
    "edit/:id": "editItem",
  }
});
var router = new Router;

And in the place where we have added our “on” methods add the following (but, again, before the Backbone.history.start(); statement)…

router.on('route:editItem', function(idParam) {
    alert('We are going to edit entry number ' + idParam);
});

So obviously we are going to try to catch an event when the user goes to http://www.yourwebsite.com/#/edit, but what is that :id thing? This is how Backbone defines a parameter. Backbone is looking for a specific item to follow the http://www.yourwebsite.com/#/edit. What happens if we go to the following URL?

http://www.yourwebsite.com/#/edit

Nothing happened. Why is that? It’s because Backbone is expecting a parameter as we defined in our route. So now try this…

http://www.yourwebsite.com/#/edit/1

Now we see that backbone is catching the id parameter and it’s getting passed into the function. This is how we can populate a single view in Backbone and have variable content passed in. What if we went to the following URL…

http://www.yourwebsite.com/#/edit/1/steve

Again nothing happens because this is passing in 2 parameters. To catch it we’d have to add another route

var Router = Backbone.Router.extend({
  routes: {
    "": "home", // url:event that fires
    "new": "createNew"
    "edit/:id": "editItem",
     "edit/:id/:name": "editItemAndName",
  }
});
var router = new Router;

And catch the event here…

router.on('route:editItemAndName', function(idParam, nameParam) {
    alert('We are going to edit entry number ' + idParam + 'and name ' + nameParam);
});

Now if we go to the URL http://www.yourwebsite.com/#/edit/1/steve we can see that the event gets caught.

Backbone also has a special variable type of parameter called a “splat.” A splat looks like the following…

var Router = Backbone.Router.extend({
  routes: {
    "": "home", // url:event that fires
    "new": "createNew"
    "edit/:id": "editItem",
    "edit/:id/:name": "editItemAndName",
    "download/*anything": "downloadItem"
  }
});
var router = new Router;

A spat basically means “match anything and everything,” so as a result if you were going to use a splat you’d want to set it as the last item in your defined route.

So if put a place to respond to this event…

router.on('route:downloadItem', function(anythingParam) {
    alert('What is stored in anything is ' + anythingParam);
});

If we pass anything after “/#/download/” all of it (slashes and all) will get passed to the anythingParam argument. If we go to http://www.yourwebsite.com/#/download nothing happens because Backbone is still expecting a parameter. However if we go to something like http://www.yourwebsite.com/#/download/path/to/my/file we can see that path/to/my/file gets passed into the parameter (slashes and all)

Now that we have defined some routes (and can easly add as many more as we want to) we are well on our way to creating a nice Backbone.js application!

Better Code Organization

Now that we have a good introductory baseline on what is happening with Backbone routers, we should take a quick look at an alternate way of organizing Backbone routes in code. We can actually respond to the events within our router and don’t need separate jQuery “router.on” for each route outside of router. For example….

var Router = Backbone.Router.extend({
  routes: {
    "": "home", // url:event that fires
    "new": "createNew"
    "edit/:id": "editItem",
    "edit/:id/:name": "editItemAndName",
    "download/*anything": "downloadItem"
  },
  home: function() {
      alert('We have loaded the home view');
  },
  createNew: function() {
     alert('We are going to create something new');
  }
  editItem: function(idParam) {
      alert('We are going to edit entry number ' + idParam);
  }
});
var router = new Router;

Notice here that we have named some properties with the exact same string names defined in our routes. You can use this approach as well if you prefer. This implementation tends to make the code a bit cleaner because everything is nicely encapsulated within our router definition.

Navigate

A Backbone.js router discussion would be incomplete if we didn’t look at the very important router method navigate. The navigate method is basically how you redirect to other locations in your Backbone application. This becomes very important when you are saving, updating, or deleting data. Often times when you, say, add a new user by filing out a form in an application and hitting the “Submit” button, the application will redirect back to the list of all users with a message that says “User Added” or something of the sort. If you didn’t do this, the person using your application would still be on the form page after hitting “Submit” which is not the best user experience because they would have to then manually navigate themselves back to the home screen.

Take a look at the implementation below. This is how navigate is called.

router.navigate('', { trigger:true });

What does this mean? This means navigate to the homepage (i.e. the ” route). Navigate by itself does not actually execute the code that we have defined in our router. All it will do is update the URL. That is why we have to pass in the { trigger: true } option to trigger the code we have defined in our route based on the path we have given. We could direct users to any location in our application that we want using navigate. The code below would navigate to the edit form for a user with ID #4…

router.navigate('edit/4', { trigger:true });

Where would you use something like this in an actual Backbone application? It’s outside the scope of this tutorial to build an entire application showing all of the places where you would use navigate, but as a brief demo take a look at the code below. In this example we are deleting an artist inside of a Backbone View. After the artist is deleted we navigate back to the homepage on successful deletion.

var ArtistDeleteView = Backbone.View.extend({
    el: '.deletePage',
    events: {
        'click .delete': 'deleteArtist'
    },
    deleteArtist: function (ev) {
        this.artist.destroy({
          success: function () {
            console.log('Artist Deleted');
            router.navigate('', {trigger:true});
          }
        })
    },
});

For more info on Backbone routers, see the documentation on the official Backbone.js site here

9bit Studios E-Books

Like this post? How about a share?

Stay Updated with the 9bit Studios Newsletter

2 Responses to Backbone.js Routers

  1. EnsteyN

    December 15, 2014 at 7:21 pm  
    You have syntax error in ArtistDeleteView. Replace },)); on }}); in the end of function

    • December 18, 2014 at 5:38 am  
      Thanks! Code updated

Leave a Reply