Add commanding, change tracking, and activity indicators to your web application when using Knockout and KoLite. KoLite (now v 1.1.0) contains a set of helpers to aid in creating data bound applications using JavaScript and Knockout. KoLite was spawned by some ideas from Hans Fjällemark and I when working on some Knockout applications. The key features are:

  • async command binding
  • <li>command binding</li>
    
    <li>activity indicator</li>
    
    <li>change detection</li></ul>
    

    Get KoLite

    You can grab the KoLite library on github or grab KoLite on NuGet.

    image

    New in KoLite 1.1.0

    1. Command binding handler supports binding to native Knockout bindings as well as the Knockout event binding for DOM events.
    2. Event object get passed on to callback on event bindings, to determine pressed key or keypress event.
    3. Added ko.command as an alternative to ko.asyncCommand for synchronous tasks.
    4. The asyncCommand's canExecute now defaults to !isExecuting if no canExecute delegate is specified. This eliminates the need of a canExecute delegate in you view-model when you only want disable the bound element when the command is executing.
    5. Explicitly do not execute commands when canExecute returns falsy. This is needed for DOM elements like the which cannot be disabled.
    6. Renamed file knockout.asyncCommand.js to knockout.command.js as it now contains both async and sync commands.

    Async Commanding and Activity

    When you use an asynchronous action that saves data across the wire, your user should know the action is still pending (via a activity indicator) and I want to prevent the button from being clicked again. The commanding technique works great for this, and you may be familiar with it if you have done any XAML work. KoLite is has an asyncCommand which handles these situations. There is also a ko.command which is ideal for synchronous actions.

    When a user clicks this button, like this

    image

    It should be disabled and show an activity indicator like this:

    image

    Just pull KoLite into your project and wrap it in an ko.asyncCommand. Just like the ICommand interface in XAML, asyncCommand has 2 methods you can define: execute and canExecute.

    saveCmd = ko.asyncCommand({
        execute: function(complete) {
            $.when(datacontext.persons.updateData(speaker()))
                .always(complete);
        },
        canExecute: function(isExecuting) {
            return !isExecuting && isDirty() && isValid();
        }
    })

    Use the execute for the logic that will perform the save and define the conditions when it is appropriate for the user to be able to execute the command. Then in the HTML set the binding to use the command and optionally, the activity indicator bindings.

    The default behavior of the canExecute is to return false while the command is executing. So if that is what you want with no additional logic, you don’t have to create the canExecute.

    You can check out this fiddle to see the asyncCommand, command and activity in action.

    Change Detection

    KoLite detects changes through its dirtyFlag. Change detection can help make a user’s experience better and frankly, can make a developer’s life a little easier. This makes it easier to disable and enable buttons for saving/canceling changes. If no changes have been made, the buttons should be disabled.

    image

    If changes have been made, then these buttons would be enabled.

    image

    We can also prevent users from navigating off the page until they have either saved or canceled their changes.

    image

    To use change detection, pull KoLite into your project.

    Tell your model which properties you want to detect changes on. (either pass an array of properties or the entire object)

    Person = function () {
        var self = this;
        self.id = ko.observable();
        self.firstName = ko.observable();
        self.lastName = ko.observable();
        self.dirtyFlag = new ko.DirtyFlag([
        self.firstName,
        self.lastName);
    };

    Create a computed property on your viewmodel and check if the model is dirty or not

    isDirty = ko.computed(function() {
        return myPerson().dirtyFlag().isDirty();
    })

    Now check the isDirty property on the ViewModel to see if changes were made or not. I can bind this property to bindings in the View, such as buttons, too.

    You can see these features being used in my Pluralsight course “Single Page Apps with HTML5, ASP.NET Web API, Knockout, and jQuery”.