Wednesday, 18 January 2012

JavaScript MVVM: Knockout.js

Knockout.js is a rich JavaScript MVVM framework for data binding HTML elements to JavaScript view models, auto UI updates, dependency tracking and templating.

For a Silverlight or WPF developer this is just what we’ve wanted to be able to unit test our presentation layer (the View Model) outside of the UI.




Example of an implementation of MVVM



Home page
Source code:


A simple Knockout.js example


Live demo:

In this example we will be:



image 1. Creating a view model in JavaScript called viewModel (see diagram).
2. Three of the properties will be ko.observables which enables data binding:
        firstName, familyName and fullNameVisible
3. firstname and familyName bound to textboxes.
4. Enforce the update of the viewModel properties after every key press by adding:
        valueUpdate: 'afterkeydown'  to the data-bind section of the textboxes
5. Binding the checked property of the checkbox to fullNameVisible along with the label.visible property.
6. Create a fourth dependentObservable property called fullName, which is dependent on firstName
and familyName and databound to “Hello {fullName}” label.

7. Bind the changeName function to the Change Name button, which updates firstName and familyName.

<!DOCTYPE html>
<script src="" type="text/javascript"></script>
<script src="" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
var viewModel = {
firstName: ko.observable("Bob"),
familyName: ko.observable("Smith"),
changeName: function () {
fullNameVisible: ko.observable(true),
viewModel.fullName = ko.dependentObservable(function() {
return this.firstName() + " " + this.familyName();
}, viewModel);
<input type="text" data-bind="value: firstName, valueUpdate: 'afterkeydown'" />
<input type="text" data-bind="value: familyName, valueUpdate: 'afterkeydown'" />
<input type="checkbox" data-bind="checked: fullNameVisible" />
<span>Hello </span><span data-bind="text: fullName, visible: fullNameVisible"></span>
<button data-bind="click: changeName">Change name</button>

Observable Arrays

Here is an example showing lists of data with validating input controls

Live demo:


<!DOCTYPE html>
<script src="" type="text/javascript"></script>
<script src="" type="text/javascript"></script>
<script src="" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
var TradeModel = function(trades) {
var self = this;
self.trades = ko.observableArray(trades);

self.addTrade = function() {
ticker: "",
price: ""

self.removeTrade = function(trade) {
}; = function(form) {
alert("Could now transmit to server: " + ko.utils.stringifyJson(self.trades));
// To actually transmit to server as a regular form post, write this: ko.utils.postJson($("form")[0],;

var viewModel = new TradeModel([
{ ticker: "MSFT", price: "39.95"},
{ ticker: "AAPL", price: "120.00"}


// Activate jQuery Validation
$("form").validate({ submitHandler: });
<form action='/someServerSideHandler'>
<p>You have entered <span data-bind='text: trades().length'>&nbsp;</span> trade(s)</p>
<table data-bind='visible: trades().length > 0'>
<th />
<tbody data-bind='foreach: trades'>
<td><input placeholder='Ticker' class='required' data-bind='value: ticker, uniqueName: true' /></td>
<td><input placeholder='Price' class='required number' data-bind='value: price, uniqueName: true' /></td>
<td><a href='#' data-bind='click: $root.removeTrade'>Delete</a></td>

<button data-bind='click: addTrade'>Add Trade</button>
<button data-bind='enable: trades().length > 0' type='submit'>Submit</button>


Built in binding

These bindings come out of the box

Text and Appearancevisible, text, html, css, style, attr
FormsClick, Event, Submit, Enable, Disable, Value, Checked, Options/Selected options (for dropdown or multi select)
Control Flowif, ifnot, foreach, with
TemplateOld:  Traditional JavaScript template (<script>)
New:  Inline, template less, comment based syntax

Custom bindings

Sometimes it’s preferred to use custom bindings over the built in bindings as it can keep your code more reusable and succinct.

ko.bindingHandlers.yourBindingName = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
// This will be called when the binding is first applied to an element
// Set up any initial state, event handlers, etc. here
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
// This will be called once when the binding is first applied to an element,
// and again whenever the associated observable changes value.
// Update the DOM element based on the supplied values here.

KO Utilities

Knockout protected observable:  Allows you to commit or undo changes to your observable data item, sweet!

Data features

You can use the built in Knockout functions to convert to |JavaScript and JSON:  ko.ToJS() and ko.ToJSON()

var viewModel = {
firstName : ko.observable("Bert"),
lastName : ko.observable("Smith"),
pets : ko.observableArray(["Cat", "Dog", "Fish"]),
type : "Customer"
viewModel.hasALotOfPets = ko.computed(function() {
return this.pets().length > 2
}, viewModel)

var jsonData = ko.toJSON(viewModel);

// Result: jsonData is now a string equal to the following value
// '{"firstName":"Bert","lastName":"Smith","pets":["Cat","Dog","Fish"],"type":"Customer","hasALotOfPets":true}'

var plainJs = ko.toJS(viewModel);

// Result: plainJS is now a plain JavaScript object in which nothing is observable. It's just data.
// The object is equivalent to the following:
// {
// firstName: "Bert",
// lastName: "Smith",
// pets: ["Cat","Dog","Fish"],
// type: "Customer",
// hasALotOfPets: true
// }

Loading and Saving JSON Data

$.getJSON("/some/url", function(data) { 
// Now use this data to update your view models,
// and Knockout will update your UI automatically

var data = /* Your data in JSON format - see below */;
$.post("/some/url", data, function(returnedData) {
// This callback is executed if the post was successful

See the knockout documentation for examples on loading and saving JSON data.

No comments:

Post a Comment