Blog Archives

ko.datasource–Enable simple binding to remote data sources

When using Knockout, we often want to bind to data that is retrieved from an AJAX request. In addition, it is not always efficient to populate the entire view model when the page loads. When adding paging, sorting and filtering of our data into the mix, if we’re not careful we can end up with a lot of accidental complexity and code duplication on our hands. To avoid that happening, I’ve created a small plugin for Knockout that makes interacting with remote datasources simple. Lets take a look.

The Bindings

I want my knockout bindings to be as simple as possible. Regardless of where I get my data, my view should be written as if it were completely unaware of where the data came from. In that vain, our markup should be the same as if we were binding to a standard knockout observable or observable array.

Let’s assume we want to display some data in a table. Our markup might look like this:

<table>
    <
thead
>
        <
tr
>
            <
th>Id</th
>
            <
th>Name</th
>
            <
th>Sales</th
>
            <
th>Price</th
>
        </
tr
>
    </
thead
>
    <
tbody data-bind="foreach: items"
>
        <
tr
>
            <
td data-bind="text: id"></td
>
            <
td data-bind="text: name"></td
>
            <
td data-bind="text: sales"></td
>
            <
td data-bind="text: price"></td
>
        </
tr
>
    </
tbody
>           
</
table>

Nothing too complicated, or unexpected. Just the basic foreach and text bindings.

Of course since we might expect a fair few results, we wish to paginate our data. Let’s add some simple bindings for this too.

<span id="pager">
    <
button data-bind="click: items.pager.first">First</button
>
    <
button data-bind="click: items.pager.previous">Prev</button
>
    <
span class="summary"
>Page 
        <
span data-bind="text: items.pager.page"></span
> of 
        <
span data-bind="text: items.pager.totalPages"></span></span
>
    <
button data-bind="click: items.pager.next">Next</button
>
    <
button data-bind="click: items.pager.last">Last</button
>
</
span>

Again, nothing too drastic – some simple buttons for pagination and an indication of what page we’re on. Do note however that we’re binding to a pager attached to the items. More on that in a moment.

The view model

The model is where the magic happens, it’s where any rich interactions will be specified. To keep our models DRY however, we probably don’t want to specify things like pagination in every view model we create. With the ko.datasource plugin, we can keep things simple:

var viewModel = {
   
items: ko.observableArray([]).extend
({
        //getAnimals is a data service to populate the viewmodel

       
datasource: getAnimals
,
       
pager
: {
           
limit: 3
        }
    })
};

We have an observableArray of items, just as if we were working with data in-memory, but two extenders have been applied to the array -  a datasource and a pager.

The datasource extender takes a single parameter; a function that will call into our remote data source. This function could, for example, use the ajax librarys of jQuery to call a webservice. We’ll take a deeper look at this in a second.

The pager extender takes a single parameter also; an object indicating how many items we would like to see per page. It will also attach itself to our observable array to expose additional pagination properties and methods. This is what the pager in our view is bound to.

The remote call

As previously mentioned, we can use our favorite library to call into whatever remote datasource we want. Let’s say we’re using jQuery’s ajax API:

function getAnimals() {
   
$.ajax
({
       
type: ‘GET’
,
       
url: ‘/my/remote/endpoint/’
,
       
data
: {
           
limit: this.pager.limit
(),
           
startIndex: this.pager.limit() * ( this.pager.page()1
)
        },
       
context: this
,
       
success: function( data
) {
           
this( data.rows
);
           
this.pager.totalCount( data.count )
;
        },
       
dataType: ‘json’
    });
};

The datasource (the extended observable array) is set as the context of the this keyword and that means we have access to the pager options. When data is successfully retrieved from our AJAX call, we can replace the data in our datasource by writing to the observable:

var observableArray = this;
observableArray(data.rows);
//or just
this(data.rows);

Additionally, since we’re using a pager, we should tell the pager how many results the server has in total so that it can figure out how many pages there are:

this.pager.totalCount( data.count );

An important thing to note is that the function we use here will behave like a computed observable, that is, it will run automatically whenever any of its dependencies change. This means that as our pager changes page, or when the row limit (records per page) changes, the remote call will be reevaluated in order to fetch the new data to show. This also means that if we pass dependencies from our viewModel as parameters to the remote call, they will also cause the datasource to be updated if they change. This is very handy as we can also use this feature for additional server-side filtering if needed.

That’s it!

Seriously, that’s all you need. Our datasource will evaluate when the view is first bound to it, and then will be reevaluated whenever our remote calls’ dependencies change.

Check out a live example here:  http://jsfiddle.net/craigcav/UzUBm/

And download the source here: https://github.com/CraigCav/ko.datasource

Enjoy.

Acknowledgements

None of this would’ve been possible without the inspiring work Ryan Niemeyer put into documenting KnockoutJS on his blog. In particular without the following two posts, this plugin probably wouldn’t exist.

http://www.knockmeout.net/2011/04/pausing-notifications-in-knockoutjs.html

http://www.knockmeout.net/2011/06/lazy-loading-observable-in-knockoutjs.html

Binding multiple event handlers to JqGrid

[UPDATE: As of version 4.3.2 (April 2012) JqGrid now uses jQuery events as described below]

If you’ve ever used JqGrid for anything more than it’s simple, out-of-the-box defaults, chances are you’ve come across problems related to how JqGrid handles events. As it stands (version 4.3.0 at the time of writing), the JqGrid API allows for one and only one event handler per user event. In particular, this approach can be a significant hurdle to constructing plugins to interpret user interactions with the grid. This post demonstrates an alternative approach using jQuery events, allowing for multiple handlers to be bound to the grid.

A full jQuery event plugin for JqGrid using this approach can be found on my github page: https://github.com/CraigCav/jqGrid.events

The JqGrid Event API

To handle events, JqGrid provides an API for specifying a callback to be executed when a named event occurs:

jQuery("#grid").jqGrid({
...
  
onSelectRow: function(id
){
      //do something interesting
 
   },
...
});

This callback can be provided as a option to the grid widget on initialization (as shown) or it can be specified after the grid has been initialized using the setGridParam method. Additionally, it can be set globally by extending the grid defaults:

jQuery.extend(jQuery.jgrid.defaults, {
...
 

   
onSelectRow: function (id, selected
) {
       
//do something interesting 
    },
...
});

Unfortunately this API limits consumers to being able to handle a single callback for each event. Given that as a developer consuming this API, I may wish to be able to provide default settings for handling an event (say, grid load for example) and I may also wish to provide instance specific options for handling the same event, this API is too restrictive to achieve what I require.

Let’s explore an alternative approach to handling user interactions.

jQuery Events

jQuery provides a standard suite of functionality specifically for registering behaviors that take effect when a user interacts with the browser. Of particular interest is the bind method; it allows for an event handler to be attached directly to an element.

$(element).bind(‘click’, function(){
   
//handle click event 
});

A key point to note about the “bind” method is that multiple handlers can be bound to an element. Each handler will be called when the event is triggered for that element.

Applying this mechanism could provide a means to achieve what we need (multiple handlers) that we currently cannot easily achieve using the JqGrid API alone. Unfortunately however, JqGrid does not currently execute any handlers attached in this manner, so our work isn’t over yet.

Triggering Events

We can use jQuery trigger or triggerHandler to work alongside our bind calls to ensure our events get triggered. Perhaps in some later release these methods will be invoked within JqGrid itself (I might submit a patch if I get around to it). Until then, we can wire up the triggers for each interesting event by setting the JqGrid options globally:

jQuery.extend(jQuery.jgrid.defaults, { 
    ...
   
onSelectAll: function (ids, selected
) {
       
$(this).triggerHandler("selectAll.jqGrid", [ids, selected
]);       
    },
   
onSelectRow: function (id, selected
) {
       
$(this).triggerHandler("selectRow.jqGrid", [id, selected
]);
    },
    ...
    
etc    
    ...
});

Each of the available JqGrid event callbacks are now used to trigger the appropriate event handlers. Instead of providing a single extension point for handling events, we can now register as many handlers for each event as we like using bind:

$(element).bind(‘selectRow.jqGrid’, function(event, id, selected){
   
//do something interesting 
});

$(element).bind(‘selectRow.jqGrid’, function(event, id, selected
){
   
//and something awesome
});

The full source of my jQuery event plugin for JqGrid can be found on my github page here: https://github.com/CraigCav/jqGrid.events

Simple inline editing with knockoutjs

A little while back, I stumbled upon a neat little trick to write pages with simple inline editing. I’m pretty sure I picked up this technique from Ryan Niemeyer’s excellent blog (although I can’t find a direct link), and I’ve seen it crop up in a few other places too. The approach has come in so handy that I’ve pieced together a little knockout binding handler to make wire up even simpler. Let’s take a look.

Inline Editing

Here’s I mean by when I talk about “Inline Editing”:

inline-edit

Example from http://addyosmani.github.com/todomvc/

The idea is that rather than having to navigate to a separate form for editing on-screen data, the user triggers an inline editor to appear instead (usually by single/double clicking), saving them time and overall improving their experience.

The Approach

The technique is that there are actually two versions of the editable element – one for viewing, and one for editing:

<div class="editor">
    <
div class="view"><a href="#"></a>Click to add</div>
    <
input class="edit" type="text" />
</
div>

Either the “view” element, or the “edit” element will be displayed, and the other will be hidden using CSS { display:none }. We can switch between the two by adding an additional CSS class to the “editor” element depending on the editing state of the view model property:

.edit {
display: none
;
}

.
editing .edit
{
display: block
;
}

.
editing .view
{
display: none
;
}

Knockout Model

We need triggers to toggle the editing state – one on double clicking, and one when we’ve finished editing. Let’s add these triggers to the view model:

var viewModel = {
   
//the item we’re editing
    item: ko.observable
(),
   
    
//track whether we are editing
    editing: ko.observable
(),
   
   
// edit an item
    editItem: function
() {
       
this.editing( true 
);
    },
   
   
// stop editing an item.
    stopEditing: function
() {
       
this.editing( false 
);
    }
};

Knockout Bindings

Since the editing state on the view model is an observable, we can use the CSS binding from knockout to apply the CSS class:

<div class="editor" data-bind="css: { editing: editing }">

We can use the text binding for the “view” element and the value binding for the “edit” input. We then need to trigger “editItem” on double click:

<div class="view" data-bind="
        event: { dblclick: editItem }, 
        text: item() || ‘Double click to edit’"
> 

…and we need to trigger “stopEditing” when we’re done editing. For simplicity, let’s use the blur binding here*:

<input class="edit" type="text" 
       data-bind="value: item, event: { blur: stopEditing }" /> 

And That’s it – Inline editing. If you’ve followed so far, you should now have something that looks like this fiddle.

*We should use other bindings here to detect the enter key being pressed, but lets keep things simple (see here for the appropriate bindings if you’re curious).

A little extra

Ok, so far so good, but what happens if we have a few of these editors in our page for different forms? If we apply this approach as is, we’d have two functions and one extra property for each inline editor. That could get out of hand quickly. Fortunately, we can apply a similar approach to the one I mentioned in my previous post – extending each model property that we want an inline-editor for:

ko.extenders.liveEditor = function (target) {
   
target.editing = ko.observable(false
);

   
target.edit = function 
() {
       
target.editing(true
);
    };

   
target.stopEditing = function 
() {
       
target.editing(false
);
    };
   
return target
;
};

Applying this extender to our model property will add the required observable to track the editing state, plus provide the trigger methods for toggling the state.

Going one step further still, we can actually have this extender applied as part of a binding handler – that way our model doesn’t have to care about the editor extender at all:

ko.bindingHandlers.liveEditor = {
   
init: function (element, valueAccessor
) {
       
var observable = valueAccessor
();
       
observable.extend({ liveEditor: this
});
    },
   
update: function (element, valueAccessor
) {
       
var observable = valueAccessor
();
       
ko.bindingHandlers.css.update(element, function () { return { editing: observable.editing 
}; });
    }
};

Link to full sample on jsFiddle.net

Simple client storage for view models with AmplifyJS and Knockout

From time to time, for a variety of different reasons, it can be desirable to use client storage to store data. There are many ways to utilize client storage but AmplifyJS is a very neat library that provides a consistent API to handle client storage that works in most browsers. This post explores a handy technique for utilizing client storage for knockoutjs based view models.

Why would I ever use client storage?

clientstorageexampleThe canonical example of this is using client storage to improve user experience, remembering user preferences or previously entered values such that the user doesn’t have to start all over.

A good example of client storage being applied can be found in the tutorials for knockoutjs. User progress in the tutorial is “remembered” and the option to restore is given when revisiting the site at a later time. The knockout tutorial site uses AmplifyJs under the hood to record user progress into client storage.

AmplifyJs

It’s pretty easy to use AmplifyJs on your site. After adding the appropriate script references, you can use amplify like this:

var item = { foo: "bar" };

amplify.store( "storeExample1", item );

The value “storeExample1” is the key that the item is stored against, and can be used to later retrieve the value as follows:

var item = amplify.store( "storeExample1" );

Now we’ve seen how easy it is to store and retrieve values using AmplifyJS, we can use this API for storing user data when it changes, and restore the value on coming back to the page at a later time. This can sometimes be easier said than done though; we have to remember to call amplify to store new values of the data whenever it changes.

Knockout to the rescue

One of knockout’s primary components, the observable, notifies subscribers of changes to it’s underlying data. It’s counterpart, the computed observable, is a function that is dependent on one or more other observables – reevaluating every time any of these dependencies change. This allows for us to easily call amplify to store data each and every time it is updated:

var target = ko.observable(amplify.store( "key" )); //populate from amplify

ko.computed( function() {

      amplify.store( "key", target()); //store new value on every change

});

target("some new value"); //setting the new value, triggering computed observable

Using this technique, we can keep our client-storage up-to-date on every change to an observable property.

One unfortunate side-effect of using this approach is that we now have to write a computed observable for every observable property we wish to store in client storage. Fortunately we can apply another knockout technique to keep our codebase DRY.

Extending Observables

Knockout includes a neat extension point that allows developers to easily augment knockout observables with additional functionality – extenders.

Applying this technique to our observable gives us a tidy way to apply client storage to any observable property:

var target = ko.observable( "default value" ).extend( { localStore: "key" } );

Any changes made to the observable value will be stored using amplify, and will be restored into the observable value when returning to the site at a later time.

The extender shown can be implemented as follows:

ko.extenders.localStore = function (target, key) {

    var value = amplify.store(key) || target();

      

    var result = ko.computed({

        read: target,

        write: function(newValue) {

            amplify.store(key, newValue);

            target(newValue);

        }

    });

 

    result(value);

 

    return result;

};

Here is a fiddle that demonstrates the localStore extender in action: http://jsfiddle.net/craigcav/QSCsK/

Processing ModelState errors returned in Json format using Knockout.js

As part of my quest to become a better JavaScript developer I’ve been experimenting with a really neat little JavaScript library called Knockout. For those unfamiliar with Knockout, here’s a very quick overview:

Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model

The rest of this post will pretty much be a brain dump of some of my recent experiments with the Knockout JavaScript library. We’ll take a little look at some typical procedural style usage of JavaScript, and then show how this can be cleaned up using a more declarative style using Knockout.

Returning Model State as Json

To set the scene, I have a small form in the application I’m working on where some complex server-side validation takes place. When this validation takes place, any broken validation rules are transformed into Json and returned to the client.

The implementation that processed the subsequent json result (based on this post) looked a little like this:

Source Code: View

<div id="operationMessage"><ul></ul></div>

Source Code: Scripts

<script type="text/javascript">

   function ProcessResult(result) {

     $("#operationMessage > ul").empty();

      if (!result.Errors) return true;

      $(‘#operationMessage’).addClass(‘error’);

      for (var err in result.Errors) {

       var errorMessage = result.Errors[err];

       var message = errorMessage;

       $(‘#operationMessage > ul’).append(‘<li> ‘ + message + ‘</li>’);

       }

       return false;          

   }

</script>

The function ProcessResult is called subsequent to receiving the response from a server side call using $.ajax(). The result object contains our list of model state errors in json format.

As you can see, the code takes responsibility for:

  1. Ensuring the UL element of #operationMessage is empty (to ensure only the messages from the current result are displayed)
  2. Adding a css class “error” if there are error messages to display
  3. Pulling out each part of the message, and appending it to the DOM

There are a couple of things worth noting here:

  • The function needs to know about the mark-up of the page, and the mark-up to use to display messages
  • The mark-up in the page needs “hooks” in the form of the id, such that the function can locate where to add messages

In essence, the “what” and the “how” of displaying error messages is all contained in one function; if either of these things are to change we risk impacting both.

Let’s see if we can do better.

View Models

The first step in separating out the concerns of our function, is to define the “what” part – what are trying to display? Let’s make that explicit using a view model. Actually, this is pretty simple for this example; we want to display a list of messages. In traditional JS, this is just an array – but since we’ll be hooking into a little Knockout goodness, we’ll use an observableArray:

var viewModel = {

    errors: ko.observableArray([])

};

The observable part is a knockout feature that lets the UI observe and respond to changes. To populate this model, we’ll simply call viewModel.errors(result.Errors) in place of calling ProcessResult.

JQuery Templates

Now we’ve defined our model, we’ll bind to this model using a jquery template. This will form the View, or the “How” part – defining how we want to display our model. First, lets define an element for our template:

<div data-bind=’template: "validationSummaryTemplate"></div>

And then the template itself:

<script type="text/html" id="validationSummaryTemplate, css: { error: errors().length > 0">

   <ul>

     {{each(i, error) errors}}

     <li>

       ${error}

     </li>            

     {{/each}}

   </ul>

</script>

Pretty concise – we’re simply defining the structure of our page in terms of our view model i.e. for each error in the view model, we’ll render a LI tag containing the error message.

Worth noting is the css-binding – remember that we want to add the error class if there are messages to display – that’s how we do it. We could push this logic onto a property of our view model if we like “hasErrors” but since this isn’t complex, or re-used elsewhere in the view, lets keep it here for now.

To apply the binding, we’ll need one final thing. We need to tell knockout to take effect:

ko.applyBindings(viewModel);

Quick Roundup

What have we gained? The “what” and the “how” are now cleanly separated, and the procedural “processing” JavaScript is completely removed. We also no longer need to dig into a JavaScript method if we wish to change the mark-up for our error items (say, to render a table instead of a list).

When writing JavaScript (much like any other language), it’s all too easy to end up with large swathes of procedural code if we aren’t careful in keeping responsibilities focused and separate.  The primary problem that face us with procedural code comes when we try to scale out complexity.

I’ve found Knockout to be a really good enabler for applying patterns such as MVVM, which in turn helps us to keep complexity at bay.

Script Management in ASP.Net MVC

In all but the simplest of modern web applications, it’s not uncommon to find that our application depends on many web assets such as CSS and JavaScript files. While it’s generally good practice for maintainability to keep these files separated into small logical chunks, unfortunately practice has implications on the overall performance of our application when referencing these resources; an additional HTTP request will be made for each asset, in turn adding to the latency of the initial load of our application.

Whilst many developers are probably aware of various optimization techniques such as those proposed in the YSlow recommendations (like script combining, minification, caching, compression), implementing these techniques can be a bit of burden.

Further still, when we utilize the Master and Content page features of our view engine, we will often want to place core JavaScript (such as the JQuery library) and common component initialization in the Master Page, whilst the Content pages may have their own file sets and initialization scripts.

This set-up adds an additional complexity to managing our scripts; we need to ensure the scripts tags are all rendered first, regardless of where they are located in the page (Master Page/Content Page/User Control) or our application will start throwing JavaScript exceptions all over the place!

Help is at hand!

Several projects exist that attempt to address some, or all of the issues I’ve mentioned (page request optimization and asset management) – lets take a look at some of our options:

Telerik ScriptRegistrar

Probably one of the closest matches to our requirements, the Telerik ScriptRegistrar and its partner in crime the StylesheetRegistrar provide a simple mechanism to provide a range of optimizations to improve the performance of our applications.  The ScriptRegistrar API is composed of a fluent interface allowing groups of scripts to be rendered at the bottom of our master page, whilst additional script dependencies and initialization can be registered in content pages. One small gotcha to look out for here is that partial views returned from Ajax requests will not have the scripts registered.

Overview

  • Resource combination (served by a IHttpHandler)
  • Grouping
  • Compression
  • Caching
  • Support for Content Delivery Networks (CDN)
  • Nice Fluent Interface for script registration and initialization
  • A Commercial License is required if you are building closed-source commercial products for redistribution (GPLv2 license).
  • Extra care is required for scripts registered in partial views rendered by Ajax calls (since these are not included by the ScriptRegistrar).
  • Minification of your scripts is not provided (although some support for selecting between pre-minified scripts and un-minified scripts in debug mode is provided)
  • Cache headers and ETags are not generated

Include Combiner

The Include Combiner project, which is included in the MvcContrib* solution as MvcContrib.IncludeHandling, tackles many of the aforementioned issues surrounding the optimization of asset management. It is not as complete as the Telerik implementation, and also suffers from the same complexity in registering scripts in partial views returned by ajax, however this tool is still worth a look for Asp.Net Mvc applications, especially for projects already consuming MvcContrib.

Overview

  • Resource combination (served by a custom controller)
  • Grouping
    • Resources grouped by page usage (rather than explicit sets) – scripts shared across pages must be re-downloaded for each page.
  • Compression
  • Minifies scripts
  • Generates cache headers and ETags
  • Simple interface for including/outputting resources
  • Included as part of MvcContrib
  • No server side caching – content is fetched every request
  • Treats JS and CSS separately, and therefore causes a minimum of 2 additional requests per page.
  • Extra care is required for scripts registered in partial views rendered by Ajax calls (since these are not included by the ScriptRegistrar).

Combres

Possibly the most complete libraries in terms of features, Combres is a strong choice for managing assets in your application. Combres requires that you define named resources sets which can then be combined, minified, compressed and sent to the browser as a single request. Interestingly, combres has an interesting extensibility model allowing developers to provide additional features, such as applying .less rules and replacing relative urls with absolute urls in css files. On the downside, the configuration model for Combres is very XML heavy, and not as nice to consume as the fluent API provided by other libraries. Unfortunately, the underlying implementation seems to wrap around the XML configuration too, so extending the library for easier consumption (applying your own conventions etc) might be tricky, especially when considered in conjunction with the fact that there are NO unit tests included in the source code (available on CodePlex).

Overview

  • Resource combination (served by a IHttpHandler and RouteHandler)
  • Grouping (Resource sets)
  • Compression (gzip or deflate depending on browser)
  • Minifies scripts (YUI compressor, MS Ajax or Google Closure)
  • Generates cache headers and ETags
  • Server side caching
  • Integrated with Asp.Net routing engine, and therefore also supports webforms development in addition to MVC
  • Extensible filtering support
  • XML heavy asset configuration model
  • Requires resource configuration upfront – as far as I can tell, there isn’t an easy way for a view component to quietly declare “I need this JS/CSS” and for it to be included if it isn’t already there

Conclusion

Optimizing our web applications and conforming to good practices like caching, combining and compressing our resources needn’t be a burden for developers. There are some great tools available to help us keep our applications nimble, whilst ensuring we aren’t distracted from delivering our customers value with technical implementation concerns. I’ve listed our some of the tools I’ve come across that bring us closer to achieving this goal.

Is there anything I’ve missed? Do you have any tools you use to optimize asset management? If so, let me know so I can check them out too!

 

*MvcContrib is a project designed to add functionality to and ease the application of Microsofts Asp.Net Mvc framework and really useful for developers looking to develop and test UI elements on top of MS Asp.Net Mvc. Check it out here.

Follow

Get every new post delivered to your Inbox.