Knockout Lite Tools (KoLite 1.1.0) | John Papa

John Papa

Evangelist on the loose

Knockout Lite Tools (KoLite 1.1.0)

...

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
  • command binding
  • activity indicator
  • change detection

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.

<button 
    data-bind="command: saveCmd, activity: saveCmd.isExecuting">
Save</button>

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”.

tags: github knockout kolite nuget open source
  • http://DotNetSpeak.com Sergey

    What would be nice is to have ko.mapping updated to automatically inject dirty flag into all the objects via some option passed in. Of course, this would only work for all the properties, which is fine in most cases.
    Thanks.

    • lakhdar

      Use angularJS for this its more complete and more clever and it simplifes the binding and you ll write less then ko

      • http://hobbscene.com Tim

        Go for it, lakhdar! The great thing is you are free to use whatever you want. No sense in coming on to someone else’s blog and trying to force your opinions in them though, don’t you think?

  • Pingback: Knockout Lite Tools (KoLite 1.1.0) | WebDevStuff | Scoop.it

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1260

  • Pingback: Friday Links #235 | Blue Onion Software *

  • http://www.sneaq.co.za Quinton

    Thanks for the article, I didn’t know kolite even existed, I was implementing similair features the old fashioned and very hard way.

    Cheers

  • Pingback: KoLite – dirty flag and more « Gregor's work related blog

  • ZSN

    Nice article and info. Can you provide a full working example of the isDirty? Also, can IsDirty be used if the viewmodel is created using the mapping?.

    I have something lihe this:

    var appViewModel = ko.mapping.fromJSON(data);

    and it works all fine, but I am not able to get the dirtyFlag working.

    Thanks.

  • Aaron Stainback

    I’m having two issues. One with activity binding and one with command binding.
    I have an enable binding and an activity binding after the activity is done and the enable is false the activity binding sets the button back to enabled. If I remove the activity this does not happen.
    With the command binding it just does not work, I get an error saying $data not defined, I’m using IE10 and knockout 3. Thanks.

  • Kristian Halvorsen

    Great library! We use asyncCommand heavily in our Durandal apllication. Run in to a problem when upgrading to knockout 3.0.0 though. The reason was that bindingContext was left out in the command bindingHandler when calling the event bindingHandler.

    I fixed this on my side, but do you have any plans for fixing this in a new release?

    • johnpapa7

      Hans is working on this updates for KoLite. You should post this to the github site issues

      • Kristian Halvorsen

        Great, thanks! Sorry about that.

  • tamiru

    I have used the dirty flag on observableArray.it removes all obersvables to intial state

    self.dirtyFlag = new ko.DirtyFlag(self.allProjects());

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

    which self.allProjects() is observableArray
    when I select the parrent observableArray it reverts back to initial state

%d bloggers like this: