3 Features You Absolutely Need in a SPA | John Papa

John Papa

Evangelist on the loose

3 Features You Absolutely Need in a SPA

...

Uh oh, someone broke your HTML app! Those darn users pressed the back button and just lost all the changes they made on the previous View! And you put all that work into building an amazing View and ViewModel pair … sigh. You coded all these great View and ViewModel (aka VVM) pairs but how do you marry them together and display them in your browser in the appropriate area?

What You Need To Know

These are issues that many HTML app developers face. You could code this “plumbing” yourself but it would quickly become something you’d feel should be shared to all of your projects. You need to handle application life-cycle for those common situations. When does your VVM load? When does it go away? What if you want to prevent (or at least interrogate) a user leaving a View/ViewModel? How do compose the View and the ViewModel? App life-cycle and VVM Composition is a critical piece of an app. How do you intercept url navigation and keep the user on the client? These 3 areas are where Durandal can really make a positive difference.

  • URL Routing
  • VVM Composition
  • App Life Cycle

spajs
Learn more about Durandal and these topics from my beginner level SPA JumpStart course for Pluralsight, available now.

Durandal

In a SPA it’s pretty darn important to be able to show a View, pair it with a ViewModel, and be able to hook into events in the app’s life-cycle. Durandal makes this super simple. You may not have heard of Durandal before as it is a newer player in this field, but it is built by the makers of Caliburn Micro, a very popular MVVM framework for .NET and XAML. It follows convention over configuration, which simply means if you name things certain ways, they just work. Kind of cool :) Of course you can override those conventions yourself too.

Is it worth learning? Yes! I rewrote my entire demo app in just a few days using Durandal and was able to reduce the code base considerably, and end up with a more fully featured app. The end result was well worth it and you will see Durandal through my course and as a featured player in Hot Towel.

Sure, Durandal has a lot of features, but let’s focus only on these 3 areas any serious SPA has to deal with: routing, app life-cycle, and composition.

URL Routing

Most apps have more than 1 View. So how do you go from View A to View B in a SPA without hitting the server for a page refresh? The answer routing (aka navigation). Let’s say you have a Sessions View and a Speakers View. You want to navigate from one to the other and stay on the client. Durandal can you help you do this.
Routing

You simply tell Durandal which routes to listen for. When It sees a route in the address bar it does a pattern match against it and if it is a route you defined, then it will not go to the server and instead it will marry up the V and VM pair.

// Inside a shell ViewModel

// Get the router module (Durandal provides this)
var router = require('durandal/plugins/router');

// Define the routes and look 
// for a V and VM pair both with the 
// same name, by convention
router.mapNav('sessions');
router.mapNav('speakers');

function activate() {
    // Tell the router to start listening for 
    // routes and where to start
    return router.activate('sessions');
}

You can override the default conventions and place your V and VM anywhere you want, but this code shows the easiest path. Make careful note that the activte method has a return statement. Durandal runs on promises, which are the promise that a method will return an answer to the code. The activate method of this code is called (we’ll see more in a bit on this) and waits to hear back for the code to be done. This is where the return router.activate statement kicks in. Without this, the caller would not know when it was done.

VVM Composition

You can put a V and VM together anywhere you like in the HTML. Usually I name my root HTML page shell.html. This is like my master page where I lay out the set of areas I want to compose V and VM pairs. I may have a header, content and footer areas, vertically. Or perhaps a dashboard with 4 content areas, 2 tall by 2 wide. How you lay it out is up to you.

Once a route is invoked you want to pair the V and VM and make the V appear in the right area. We do this through composition. Notice the image below shows the HTML section tag contains a compose binding. This is a custom Knockout binding that Durandal uses to help you compose the V and VM.

The section tag will go get the current item that was navigated to and find its V and VM pair. It will place the View in this HTML tag and when it is done, it will invoke the afterCompose (this is a handy feature that enables things like turning of a progress bar while composing). You can also use the entrance transitionwhich comes with Durandal or write your own to animate the arrival of the V.

   <section data-bind="
            compose: {model: router.activeItem, 
            afterCompose: router.afterCompose, 
            transition: 'entrance'}">
    </section>

If you want more areas, just create more HTML tabs and compose bindings. You can also make a V share a VM, as I explain more in my course. This is handy for composing a few Views that all share a VM.

App Life Cycle

The life-cycle of your VVM pair is important. You may need to load data when you crank up a VVM pair. Maybe you want to perform some logic before you leave a VVM pair. You can do this easily with Durandal.
Picture1

Durandal will look for these 4 methods in your VM. When one of the events occurs, Durandal will look in your VM and if it finds one it will invoke it. They are pretty self explanatory.

  • activate
  • deactivate
  • canActivate
  • canDeactivate

If you want to cancel one of the can events, then return false.

// Inside your ViewModel
var canDeactivate = function () {
    var title = 'Do you want to leave?';
    var msg = 'Navigate away and cancel? ';
    return app.showMessage(title, msg, ['Yes', 'No '])
        .then(function (selectedOption) {
        if (selectedOption === 'Yes ') {
            // Call some cancel function
            cancel();
        }
        return selectedOption;
    });
};

return {
    activate: activate,
    canDeactivate: canDeactivate //,
    //...
};

There is so much more you can use Durandal to do, but these 3 concepts are absolutely huge in helping build a SPA. If all you use it for are these 3 tips, then you are getting your value.

Next time I’ll talk a about how to get rich data using BreezeJS.

SPA Jump-Start Series

tags: durandal javascript SPA
  • Pingback: 3 Features You Absolutely Need in a SPA | WebDevStuff | Scoop.it

  • Pingback: John Papa interview on SPA (Single Page Applications) - SSW TV | SSW TV

  • Phil

    Hi John,

    Loving the SPA courses so far. As a relative newbie to Web development and being somewhat restricted in the hardware I’ve got available to play with I’m interested to know how well, if at all, this all this maps into Touch interfaces. Do you get that out of the box or is there additional work to do?

  • http://www.trisys.co.uk Garry@TriSys

    Can please you supply a link to the working application so we can see what a proper SPA looks like and how it performs on a range of devices?

    • John

      The live demo is here http://jpapa.me/ccjsdemo

      • http://www.trisys.co.uk Garry@TriSys

        Thanks John – great to actually see a working SPA app.
        As a developer, generally I’d look first at the working application on-line rather than be forced to download it, recompile it and run it.
        Keep up the great work.

        G.

  • Justin Jeremie

    Hello John,
    I have started taking your SPA Jumpstart course on the Pluralsight site. Can you please share your opinion on using the SPA approach to create a web based card game? I would greatly appreciate your thoughts on this. Thanks.

    • John

      Justin – You can certainly create a gaem with a SPA. Rob, the creator of Durandal, has a RPG he created with it, I believe. I’d love to create a game … been many years since I have. Might be a fun challenge with SPA

  • Conrad

    Hi John, thanks for blogging, it’s really appreciated.

    I notice you are hosting your demo on Azure. Are you using ASP.net routing to route all requests to your default.htm (or whatever your root page is)? Or am I misunderstanding how routing in SPAs work?

  • http://www.wrapcode.com/ Rahul P

    How can I refresh view? I need to reload the list by making one more API call.. I don’t wanna write code for that.. Is there any way to reload the same view rather?

%d bloggers like this: