A few weeks ago, I posted a simple example of a Single Page Application (SPA) built with Backbone.js, ASP.NET Web API, F#, C#, and more. Today, I’m posting a similar example, but built with Knockout.js. Let’s look at some of the code.

View:

Knockout.js supports binding of model data directly to DOM elements, so the first thing that we will look at is one of the templates that are used for the views. Here’s what this example uses for the contacts list view template:

The main thing to notice in this markup is the use of the data-bind attributes to bind specific model data to the appropriate DOM elements.

ViewModel:

The example defines a single ViewModel that is used for both of the available views. The code, which is fairly similar to that described at http://knockoutjs.com/examples/contactsEditor.html, is shown below:

Router:

Another thing to notice is the routing mechanism used in this example. Since Knockout.js doesn’t provide built in URL routing, I’ve used Sammy.js to accommodate the need. Here’s what the router looks like:

(function ($) {
    appFsMvc.App = function( contactsViewModel ) {
        return $.sammy( "#content", function () {
            var self = this;

            this.use( Sammy.Cache );
            this.contactViewModel = contactsViewModel;

            this.renderTemplate = function ( html ) {
                self.$element().html( html );
                ko.applyBindings( self.contactViewModel );
            };

            // display all contacts
            this.get( "#/", function() {
                this.render("/Templates/contactDetail.htm", {}, function ( html ) {
                    self.renderTemplate( html );
                });
            });

            // display the create contacts view
            this.get( "#/create", function() {
                this.render("/Templates/contactCreate.htm", {}, function ( html ) {
                    self.renderTemplate( html );
                });
            });
        });
    };

    $(function () {
        $.getJSON( "/api/contacts", function ( data ) {
            var viewModel = new appFsMvc.ViewModels.ContactsViewModel( data );
            appFsMvc.App( viewModel ).run( "#/" );
        });
    });
})(jQuery);

ApiController:

Lastly, we’ll get a quick look at the API Controller that is written in F#. Here’s the code:

open System.Web.Http
open FsWeb.Models

type ContactsController() =
    inherit ApiController()

    let contacts = seq { yield Contact(FirstName = "John", LastName = "Doe", Phone = "123-123-1233")
                         yield Contact(FirstName = "Jane", LastName = "Doe", Phone = "123-111-9876") }

    member x.Get() = 
        contacts
    member x.Post ([<FromBody>] contact:Contact) = 
        contacts |> Seq.append [ contact ] 

That’s pretty much it. You can find the full solution at https://github.com/dmohl/FsWebSpa-Knockout.

 
  • Webspinner90

    Isn’t it bad to call ko.applyBindings multiple times?