Web applications are now expected to be as responsive and immersive as desktop applications. In my opinion, Single Page Applications or SPAs are where the web is going and many sites you are already familiar, with such as Gmail, are already there. However writing an application on the web poses some unique concerns. Being on the web, users will expect the forward and back button to work and to be able to bookmark pages. Having a SPA poses some problems since everything is done on a single page. So how do you provide support for back and forward buttons and support for bookmarks? Enter Sammy.js

Benefits of using Sammy.js

  • Bookmarking a “page” in your SPA
  • Forward and back button still work as expected
  • Avoiding Postbacks/Minimal Network traffic, because this is a single page there is no need for the browser to reload the page each time you navigate, so almost all computation is done client side providing a significant speed boost.
  • Avoiding session, because we have actual URLs there is no need for your application to remember where you are, eliminating the need to store the users current state in session or something similar which can be a problem in traditional AJAX sites.

The heart of Sammy.js is allowing you to define routes in your JavaScript very similar to how you set up routes in MVC. The first step is to set up the base route. This is what will be fired when no other route is defined. In order for Sammy to work you must setup the routes right after the DOM is fully loaded before you have any other actions in you JavaScript.

(function ($) { 
    var app = $.sammy('#MainSection', function () { 
        this.get('#/', function (context) {
            DoSomethingHere();
        }); 
    });  

    $(function () { 
        app.run('#/');
    });
})(jQuery);

Above I am defining the main content area of my SPA as MainSection. You can also explicitly define the main content area (see below), but you can just use the short hand as shown above to keep things simple.

this.element_selector = '#MainSection';

After defining the main content area I am defining my default route. So whenever the users navigates to a URL matching www.myapp.com/, www.myapp.com/# or www.myapp.com/default.html/# it will call the DoSomethingHere() method. After defining the default route you must initialize the application. If you do not initialize the application by calling app.run() then the routing engine will not take over and none of your routes will work.

Now let’s try for a little more complex route. I want a URL that will show employees. So I am going to define a route that looks like www.myapp.com/default.html#/Employees. We are going to declare this route right below the default route in the example above.

this.get('#/Employees', function (context) {
   ShowEmployees();
 });

So anytime someone navigates to the URL above it will run the ShowEmployees functions. If you have any experience with the MVC framework this should look very familiar to you. Now if we wanted to continue along those lines and wanted to view a specific employee based on that employee’s ID then we can use the following pattern www.myapp.com/default.html#/Employees/5 and define a route to match.

 this.get('#/Employees/:id', function (context) {
    LoadEmployee(this.params['id']);
 });

The :id tells the routing engine to expect a variable after the ending slash. To access this variable you just call this.params[] and give the name of the variable in quotes and you are ready to use it. So now that we have the routes down how do we actually use it? You simply add an anchor tag to your site that matches a route. The below example shows how you would add a link to view employee number 5:

   <a href="#/Employees/5" >John Doe </a>

When the user clicks the link above, the page life cycle looks something this:

  1. Page navigates to the # anchor on the page (doesn’t actually exist) loads DOM
  2. Sammy.js recognizes the pattern from your defined routes
  3. Your method LoadEmployee gets fired, where you change the main content to display information about John Doe.
    1. Presumably you are making an AJAX call to pull employee data back via JSON, or if you are using an HTML5 compatible site, you can load all your employee data when the user first lands on your site and store everything in local storage. There are pros and cons to each method, but that is out of scope for this post.
  4. After LoadEmployees returns the rest of your JavaScript on the page fires. For example, if you are using JQuery this is when the document.ready function would fire.
  5. Display the rendered page to the user.

In summary, by using Sammy.js you can create and define routes in your single page applications that will allow users to navigate as they normally would on the web without the extra overhead of continuously posting back to the server.

This is cross posted at TCSC.com