JavaScript is a great language, but building complex user interfaces for websites and web apps using JavaScript alone can get tedious and fiddly. You have to deal with cross-browser issues, as well as write long-winded functions to manipulate the DOM (document object model), handle events, and more.

For this reason, a large number of useful JavaScript libraries have emerged in recent years to make your job as a JavaScript coder easier and more fun.

One recent library that's growing in popularity is Knockout. It's small, easy to use, and plays nicely with other JavaScript libraries such as jQuery. Using Knockout, you can build complex user interfaces in a fraction of the time that it would take you to code everything by hand.

In this tutorial, you learn Knockout from the ground up. You explore the key concepts behind Knockout, and learn how to create interactive web pages quickly and easily. At the end of the tutorial, you work through a complete "product selection" example that shows how to use Knockout in practice.

Press the View Demo button above to view the complete "product selection" example. You can also press the Download Code button to download all the code examples from this tutorial.

By the time you've finished reading, you'll be able to build rich, interactive web pages using Knockout, and you'll be well on the way to becoming a Knockout expert!

Let's kick things off with a brief look at Knockout's philosophy, features, and benefits.

What is Knockout?

Knockout is a small JavaScript library that makes it really easy to create interactive user interfaces for your websites and web apps. It's based on a coding pattern called Model-View-Viewmodel (or MVVM for short).

You create a JavaScript view model object that holds all the data that appears in your view, and link the view model with the view using bindings.

Then, any changes you make to the data in the view model object automatically update the widgets in the view.

Conversely, if the user changes something in the view — such as selecting a checkbox — then the data in the view model updates automatically. (This, in turn, can cause other widgets in the page to update automatically.)

The great thing is that, once you've created your view and view model, Knockout updates them automatically, without you having to write any tedious JavaScript code to access and manipulate the DOM yourself. This saves you a lot of time, and gives you a nice clean separation between your web app's logic and its user interface.

Knockout's main features

Knockout revolves around the following main features:

The view: The HTML document that displays the user interface.

The view model: A JavaScript object that represents all the data and operations in the view.

Bindings:data-bind attributes that you add to various HTML elements in the view. The bindings link those elements to the data in the view model.

Observables: Values you add to the view model that have a two-way binding to an element, or elements, in the view. When an observable value in the view model changes, so does the view, and vice-versa.

Computed observables: Observables that compute their values based on the values of other observables. Knockout cleverly tracks dependencies, so that whenever an observable's value changes, any computed observables that use that observable are run automatically to compute their new values.

Templates: Snippets of HTML markup that Knockout inserts into the view as required. For example, a template might only be inserted if a certain condition is true, or you can create a loop to repeatedly insert a template containing an li element into a list.

Let's take a look at some of these key features, starting with views, view models, and bindings.

Creating views, view models and bindings

Here's a very simple example Knockout page that creates a view, a view model, and a binding between the two:

The JavaScript includes
Inside the page's head element, we've added a couple of JavaScript includes: jQuery on Google's CDN, which we'll use in the examples in this tutorial, and the Knockout library itself, which is stored in a single JavaScript file, knockout-2.1.0.js.

The view
The view is the user interface. In this case, it's simply an h1 element with the page title, and a p element containing the message "Your selected product is: ", along with a span element to hold the product name.

The view model
The JavaScript code at the top of the document creates a view model class, ViewModel. The class contains a single property, productName, holding the value "WonderWidget". After creating the ViewModel class, the code uses the jQuery $() method to wait until the DOM is ready before calling the Knockout method ko.applyBindings(), passing in a new ViewModel object. This activates Knockout and associates the view model with the current view — that is, the web page.

The binding
On line 28, our view's span element has the attribute data-bind="text: productName". This tells Knockout to link the text inside the span with the value of the productName property in the view model object. When our code calls ko.applyBindings(), Knockout goes through the markup, finds the data-bind attribute, and inserts productName's value inside the span.

At the top of the ViewModel class (line 12), we assign the JavaScript pseudo-variable this (which, at that point, represents the current object) to a local variable called self. Then we use self whenever we want to refer to the current object, rather than this.

Why do we do this? Well, in JavaScript the value of this can change depending on the context in which the object's functions are called. This happens frequently when working with Knockout. By assigning this to self at the start of the class, we ensure that we'll always have a reference to the current object. For more details on this convention, see "Managing 'this'" on Knockout's Computed Observables page, and this good discussion on Stack Overflow.

Adding observables

We've now created a basic Knockout example, with a view, a view model, and a binding to link the two together. However, this page isn't interactive at all — it doesn't do anything after it's displayed.

To take our example to the next level, it would be great if we could let the user interact with the page after it's loaded. For example, the user could click a button to change the value of the productName property. Then the span's text in the view should update itself accordingly. Let's try it:

Although the productName property does change to "SuperWidget" when the button is clicked, the span's text doesn't update automatically to reflect the new value. This is because Knockout has no way of knowing that the property's value has changed.

Doing it right

To fix this problem, we need to replace our productName property with — you guessed it — an observable. An observable is a value that Knockout can track, so that whenever the value changes in the view model — even after the page has loaded — Knockout automatically updates any bound HTML elements in the view.

You create an observable in your view model like this:

observableName = ko.observable( initialValue );

This creates a new observable, observableName, with an optional starting value, initialValue. (If you miss out initialValue then the observable's value is undefined.)

You then read an observable's value like this:

currentValue = observableName();

...and change the observable's value like this:

observableName( newValue );

Within your view, you access an observable through a data-bind attribute, just like you reference a regular property:

data-bind="text: observableName"

OK, now we can rewrite our simple example above, replacing the productName property with a productName observable:

I've highlighted the important changes in the code above. As you can see, we create a new observable called self.productName inside the view model, and give it the initial value "WonderWidget". Then, in the click handler, we change the observable's value to "SuperWidget".

Notice that, when you click the Change Product button, the text in the page changes to:

Your selected product is: SuperWidget.

As you can see, this change happens automatically. We don't need to explicitly write any code to update the DOM. This is one of Knockout's main strengths.

Two-way observables

Observables get even better. If you create a binding between an observable and an HTML element that the user can update — for example, a text field — then whenever the user changes the value in the element, Knockout updates the observable value in the view model automatically. This means you can easily create a two-way link between the data in your view model and the widgets in the view, all without having to write tedious JavaScript code to access the DOM. Nice!

Let's try this out. We'll remove the Change Product button from our example, and replace it with a text field bound directly to the productName observable:

As you can see on line 33, we've added an <input type="text"> field to the page. The field includes the attribute data-bind="value: productName". This binds the text field's value to the productName observable.

Try typing a new value, such as "My Great Widget", into the text field and pressing Return. Notice that the text in the page automatically updates to:

Your selected product is: My Great Widget.

When you change the value in the text field, this automatically updates the productName observable. This, in turn, automatically updates the paragraph of text in the page.

More on bindings

In addition to the text and value bindings, there are a range of other useful bindings that you can use to link HTML elements in the view with observables in the view model. We'll look at some of these throughout the tutorial. Here's a quick summary of the built-in Knockout bindings:

visible

Hides the element if the observable's value is false.

text

Makes the element display the observable's text value.

html

Makes the element render the HTML string stored in the observable.

css

Adds or removes a CSS class on the element, based on the result of an expression.

style

Adds or removes an inline CSS style on the element, based on the result of an expression.

attr

Sets any attribute of the element to the observable's value.

foreach

Loops through an array, duplicating a chunk of markup for each array item. Handy for lists and tables.

Assigns a specified JavaScript function to be the click event handler for the element.

event

Assigns a specified JavaScript function to be a specified event handler for the element.

submit

Assigns a specified JavaScript function to be the submit event handler for a form element.

enable

Enables a form field if the observable's value is true, and disables it if the value is false.

disable

Disables a form field if the observable's value is true, and enables it if the value is false.

value

Creates a two-way binding between an observable and a form field's value. This includes text fields, textareas, and select menus.

hasfocus

If the observable is set to true, this binding focuses the element. If it's set to false, the binding unfocuses the element. Similarly, if the user focuses or unfocuses the element, the observable becomes true or false.

checked

Links a checkbox or radio button's checked status with an observable. If the observable is set to true or false then the element is checked or unchecked automatically. Similarly, if the user checks or unchecks the element then the observable is set to true or false respectively.

options

Populates a select menu's options with the values in an array (or an observable array).

selectedOptions

Creates a two-way binding between an observable array and the selected options in a multiple select menu.

uniqueName

Adds a unique name attribute to the element, if it doesn't already have one. Handy for plugins and browsers that require an element to have a name attribute.

template

Lets you explicitly set an element's content to the results of rendering a named template (that is, a chunk of markup, usually containing data-bind attributes).

Creating observable arrays

An observable array allows your view model to keep track of a whole group of items at once. This is handy if your user interface contains user-editable lists of items, such as select menus, tables, or groups of checkboxes. You can easily bind an observable array to such elements, and let Knockout take care of updating the contents of the array as the user adds and removes items in the list.

You create an observable array like this:

observableArrayName = ko.observableArray( initialValue );

You can pass an optional initial array in order to pre-populate the observable array. For example:

selectedItems = ko.observableArray( [1,2,3] );

If you don't supply an initial array then the observable array starts out empty.

Once you've created your observable array, you can access the underlying JavaScript array by calling the observable array as a function, like this:

observableArrayName()

For example, you can display the first element inside a selectedItems observable array like this:

alert( 'The first selected item is ' + selectedItems()[0] );

Although you can manipulate the underlying array using JavaScript's array functions, such as push(), splice() and indexOf(), Knockout provides its own equivalent functions that you can use directly on the observable array. Not only are these functions more convenient, but they also work across all browsers and link up with Knockout's dependency tracking, so that when you modify an array the corresponding elements in the view get updated automatically.

For example, you can use push() add a new item to the end of an observable array, like this:

observableArrayName.push( newItem );

You'll find a full list of Knockout's observable array functions on this page.

This example contains two select menus: a list of available products, and a list of selected products. You can select a product in the first list and press the Add Product button to move the product to the second list. Similarly, you can select a product in the second list and press Remove Product to move it back to the first list.

The availableProductsselect menu
This holds the list of products that the user can select from. It has an options binding that binds the options in the menu to the availableProducts observable array (which we'll look at in a moment). This means that whenever an item is added to or removed from the observable array, the options in the select menu update automatically.

The menu also has a value binding that links the selected item with the productToAdd observable. So whenever the user selects an item, productToAdd automatically updates to contain the selected product name. Conversely, if the productToAdd observable is changed in the view model, the selected item in the select menu changes automatically to match.

The Add Product button
After the Available Products menu is an Add Product button that adds the selected product to the Selected Products menu. This button has two bindings: click, which calls an addProduct() method when the button is pressed, and enable, which enables the button when the productToAdd observable contains a non-empty value (and disables it if productToAdd is empty).

The selectedProductsselect menu and Remove Product button
These two widgets are the counterparts of the availableProductsselect menu and Add Product button. selectedProducts holds the list of products that the user has added, and contains bindings to the selectedProducts observable array and the productToRemove observable. The Remove Product button contains a click binding to the removeProduct() method to remove a product from the list, and an enable binding that enables the button only if the productToRemove observable is non-empty.

The availableProducts and selectedProducts observable arrays
In the JavaScript at the top of the page, we create the two observable arrays: availableProducts to hold the list of products to select (initially populated with the values "SuperWidget", "MegaWidget" and "WonderWidget"), and selectedProducts to hold the list of products that the user has selected (initially empty). Since these are bound to the select menus in the view, the select menus will update automatically whenever items are added to or removed from these arrays.

The productToAdd and productToRemove observables
Next we create two observables, productToAdd and productToRemove. These are bound to the availableProducts and selectedProductsselect menus respectively, using their value bindings. This means that, when the user selects an item in one of the menus, the corresponding observable value is automatically updated. Similarly, if we update the observable, the corresponding value in the menu is automatically selected.

The addProduct() method
Our view model contains an addProduct() method that runs when the user presses the Add Product button. The method's job is to move the selected product from the availableProducts menu to the selectedProducts menu. The method does this in four steps:

It adds the selected product — stored in the productToAdd observable — to the selectedProducts observable array. (The select menu updates automatically.)

It selects the newly-added item in the selectedProducts menu by setting the productToRemove observable's value to the name of the added product.

It removes the added product from the availableProducts observable (and therefore the select menu).

It selects the first item in the availableProducts menu by setting the productToAdd observable to the first product in the availableProducts observable array.

The removeProduct() method
This method runs when the user presses the Remove Product button. It is the exact opposite of the addProduct() method: it moves the selected product in the selectedProducts menu back to the availableProducts menu.

With this example, you can see how powerful observable arrays can be. By linking observable arrays to select menus in the view, you can let Knockout take care of the tedious work of updating the menus when the view model changes, and vice-versa.

You can use observable arrays with other "list" UI elements too. Later in the tutorial, you'll see how to bind an observable array to a group of checkboxes.

Creating computed observables

As well as holding simple values and arrays of values, observables can also be functions that calculate and return a value. These are called computed observables. You create a computed observable like this:

Computed observables have a very important feature. Say a computed observable uses the values of some other observables to carry out its calculation. If any of these observables' values change, Knockout automatically re-runs your computed observable so that its value is updated too.

For example:

You create a computed observable, A, that uses the value of another observable, B, and another computed observable, C, to compute its value.

The computed observable C uses two other observables, D and E, to compute its value.

If B's value changes, Knockout automatically re-runs A to compute its new value.

If either D's or E's value changes (or both values change), Knockout automatically re-runs C to compute its new value. Since C's value has now also changed, Knockout also re-runs A to compute its new value.

In this way, you can chain as many observables and computed observables together as you like, and Knockout handles all the dependencies automatically.

To start with, you'll see a prompt telling you to enter your first and last name, and your location. Fill in the three text fields in the page, and press Return. Notice that the prompt changes to a greeting that includes the data you entered into the fields.

Let's take a look at our code and see how it works:

The view
The view contains a paragraph element whose text value is bound to an observable called greeting. It also contains the three text fields — firstName, lastName and location — whose values are bound to the firstName, lastName and location observables respectively.

The standard observables
On lines 15-17, our view model defines three regular Knockout observables, firstName, lastName and location, and gives them each an initial value of "" (an empty string).

The fullName computed observable
On lines 20-22, we've added a computed observable called fullName to our view model. This function simply concatenates the values of the firstName and lastName observables (with a space in between), and returns the resulting string. Whenever the value of either firstName or lastName changes, fullName is automatically run to compute the new value.

The greeting computed observable
On lines 25-31, we've added a second computed observable, greeting. This function constructs the greeting message to display to the user, based on the value of the fullName computed observable, as well as the value of the location observable.

If either the fullName or location values are empty, greeting returns the "Please enter your..." prompt instead.

Again, if the value of either fullName or location changes, Knockout recognizes the dependency and automatically re-runs greeting's function to compute the new value. What's more, since the paragraph in the view is bound to the greeting computed observable, the moment greeting's value changes, the text in the paragraph automatically updates to the new value.

As you can see, computed observables make it really easy to create complex user interfaces. When the user changes one widget in the page, a bunch of other widgets in the page can update automatically, without you having to write the code to explicitly manage the dependencies. This is powerful stuff!

By default, computed observables are "read-only" — a widget in the view can't update the value of a computed observable, since you can't change the value of a function. However, two-way computed observables are possible, and rather useful. See the section "Writeable computed observables" in Knockout's Computed Observables page.

Under the hood, Knockout implements all the bindings in your view as computed observables. So whenever an observable value changes in the view model, the relevant values and widgets in the view update automatically.

A complete example: Widget Shop

Let's bring together many of the concepts you've learned in this tutorial and build "Widget Shop", a complete product selection page using Knockout. Our page will have the following features:

The page pulls some JSON product data from the server via Ajax, and displays four product thumbnails, along with the product names.

When the user clicks a thumbnail, a "product info" box appears, containing the product name, price, full-size product image, description, options, a Quantity field, and a Buy Now button.

The user can select different product options and change the quantity. The price inside the Buy Now button updates automatically.

When the user presses the Buy Now button, the selected product data is sent to the server via Ajax. (In our example, we'll simulate this by simply displaying the JSON data in an alert box.)

Try clicking a product to select it, then adjusting the options and quantity. When you're done, press the Buy Now button to see the JSON data that the app would send to the server.

The product data file

Let's start with the JSON product data. Normally this would be pulled dynamically from a database using a server-side script (such as PHP), but to keep things simple we'll create a static text file instead. Create a widget-shop folder somewhere in your website, and save this file as products.txt inside the widget-shop folder:

If you're familiar with JSON then this file should be pretty straightforward. It represents four products: SuperWidget, WonderWidget, MegaWidget and HyperWidget. Each product has various attributes, including a unique ID, a name, a price, a description, thumbnail and full-size image filenames, and an options array containing a list of product options, each with a unique ID, a name, and a price.

If you're not familiar with JSON, check out my JSON Basics tutorial for a gentle introduction.

The view

Now let's create our view — that is, the page that the user interacts with. Save the following file as choose-product.html inside your widget-shop folder:

The includes
As well as our usual jQuery and Knockout includes, we also include a style sheet, style.css, and a choose-product.js JavaScript file that will contain our view model and other functions. (We'll create these files in a moment.)

The call to getProducts()
When the page DOM is ready, we use jQuery's $() method on line 13 to call getProducts(), a function within choose-product.js that grabs the product data and starts Knockout running.

The product thumbnails
On lines 25-30, we create a ul element to hold the list of products. We add a foreach binding to the element that links a products array in the view model with the list. This makes Knockout loop over the products in the array, rendering the supplied li element template for each product object in the array.

We add two bindings to the li element itself: a click binding that runs the view model's chooseProduct() method when the user clicks the product, and a css binding that calls the view model's productSelected() method, passing in the current product object's id property. If this method returns true, the binding adds the selected CSS class to the li to highlight the selected product.

The special Knockout property $parent refers to the parent of the products array — that is, the view model object. Find out more about $parent, and other special properties, in the Knockout documentation.

Within the li, we add an img element with an attr binding. The binding adds two attributes to the element: src, to link the element to the product's thumbnail image file (stored inside an images folder), and alt, to set the image's alternate text to the product name. It gets these two pieces of data from the current product object's thumbImage and name properties. We also add a span element that displays the product's name, again pulled from the object's name property.

The chosenProductdiv
The div with the id of chosenProduct, on lines 32-54, displays the selected product details. We add a visible binding to it so that it's only shown when the chosenProduct observable is not empty — that is, the user has chosen a product.

The product name and base price
Within the chosenProductdiv, we first add an h2 element on line 34 containing two spans. The first span displays the selected product's name by retrieving the name property of the product object stored in the chosenProduct observable in the view model. The second span displays the product's price by retrieving the product object's price property.

The main product image
Next, on line 35, we add an img element to the chosenProductdiv to display the main product image. As with the thumbnail, we add a src attribute pointing to the image in the images folder, and an alt attribute containing the product name. We pull this data from the currently-chosen product's mainImage and name properties respectively.

The productInfodiv
This div, on lines 37-52, contains the product description, options, Quantity field, and Buy Now button.

The product description
On line 39, we add the product's long description inside the productInfodiv as a p element. The element has a text binding to the currently-chosen product's description property.

The product options
On lines 41-47, we add a "Customize Your Product" heading, along with a ul element containing the product's options. Much like the product thumbnails above, we use a foreach binding to the chosen product's options array to display one li per option. We add a css binding to each li that calls the view model's optionSelected() method to determine if the current option is selected; if it is then we add a selected CSS class to the li to highlight it.

On line 45, within each li, we add a checkbox with two bindings:

value, which we bind to the current option object's optionId property

checked, which we bind to the view model's chosenOptions observable array. Knockout then associates the checkboxes with this array, so that whenever the user checks or unchecks a checkbox, the checkbox's value is added to or removed from the chosenOptions array automatically. Nice!

The li also contains the option's text, pulled from the current option object's name property, and the option's price, pulled from the price property. We wrap the whole lot in a label element so the user can click anywhere in the li to toggle the checkbox.

The onclick handler that we've added to the label element works around a known bug in Mobile Safari that prevents a label from being tapped to select a form field.

The Quantity field
On line 49, we add a Quantity field allowing the user to choose how many of the product they'd like to buy. We bind its value to a qty observable in the view model.

The Buy Now button
Finally, on line 50 our view includes a Buy Now button. We set the view model's buyProduct() method as a click handler for this button. We also insert the total price into the button's text using the totalPrice computed observable. This observable, which you'll create in a moment, calculates the total price on the fly based on the selected product, any chosen options, and the value of the Quantity field.

The view model and other JavaScript

The other important part of our widget shop is the JavaScript to create the view model object and fetch the product data from the server. Save the following file as choose-product.js inside your widget-shop folder:

The getProducts() function
This function is called from the choose-product.html page when the DOM is ready. First it uses jQuery's getJSON() method to pull the JSON product data from the products.txt file on the server and turn it into a JavaScript object.

Once the data is loaded and the data object has been created, the function preloads all the main product images by storing them in an array of Image objects; this ensures that the user doesn't have to wait for the main product images to load. The function then creates a new ChooseProductViewModel object and passes the data object's products property to the constructor so that the view model object can store the product data. Then it calls Knockout's ko.applyBindings() method, passing in the new view model object, to start the ball rolling.

The view model
The rest of the JavaScript file defines the ChooseProductViewModel class that we use to create our view model object. On line 21, we start the class definition, accepting the array of product objects in a productData parameter. Let's take a look at each chunk of code in our view model...

Store 'this' in 'self'
As usual, on line 24, we store the this special variable in the self local variable so we always have a reference to the current object.

Store the retrieved list of product objects in the view model
On line 29, we store the product data passed to the view model in a local self.products property, so that we can easily access it from the view.

Create Knockout observables for various parts of our view
On lines 32-34, we create three observables to link to our view:

chosenProduct will store the currently-selected product object. We set this to false initially. This is used throughout the view to access information about the chosen product.

chosenOptions is an observable array holding the IDs of any product options that the user has selected. This array is linked to the option checkboxes in the view.

qty maps to the Quantity field in the view. It's set to 1 initially.

The totalPrice computed observable
On lines 38-64 we define a computed observable, totalPrice, that calculates the total price for the Buy Now button on the fly. This function retrieves the currently-chosen product and stores its base price in a local price variable. Then it loops through the available options in the currently-chosen product, as well as all the selected options in the chosenOptions observable array. Each time it finds a product option that has been selected, it adds its price to the price variable. Finally, the function multiples the total price by the value of the qty observable, rounds the resulting value to 2 decimal places, and returns the final price.

In theory you could replace the inner for loop in this function with Knockout's indexOf()observable array method. However, I found this method to be somewhat buggy in Firefox 12, so I manually looped through the array instead.

The chooseProduct() method
The chooseProduct() method, defined on lines 69-72, runs when the user clicks a product thumbnail. It accepts the chosen product object as a parameter, product, then sets the chosenProduct observable to this object. Since all the widgets inside the chosenProductdiv in the view are bound to the chosenProduct observable, changing this observable's value automatically updates all of those widgets.

On line 71, we also use jQuery to slowly scroll down to the chosenProductdiv in the view. This creates a nice smooth transition, especially on mobile phones.

The optionSelected() method
On lines 77-87, we define an optionSelected() method, which determines if a given product option has been selected by the user. The method accepts an optionId argument. It then loops through all the selected options in the chosenOptions observable array. If it finds the optionId value in the array then it returns true; otherwise it returns false.

This method is bound to the product option li elements using the css binding. If the method returns true then the CSS class selected is applied to the li, highlighting it. If it returns false then the CSS class is removed.

The productSelected() method
Lines 95-97 define a productSelected() method. Much like the optionSelected() method, productSelected() returns true if the product with the supplied ID has been selected by the user, and false if it hasn't. It simply compares the supplied ID against the ID of the product object stored in the chosenProduct observable. This method is bound to the product thumbnail li elements using a css binding, so that the selected class is added to the li if the product is selected, highlighting the li element.

The buyProduct() method
Finally, on lines 102-127 we define a buyProduct() method, which runs when the user presses the Buy Now button in the view. The method simply creates a data object containing three properties:

chosenProductId, pulled from the id property of the product object stored in the chosenProduct observable.

chosenOptions, which we calculate as the intersection between the chosenOptions observable array and the options associated with the chosen product (so that we only include selected options for the currently-selected product).

qty, pulled from the qty observable.

Once it's constructed the data object, the method turns it into a JSON string by calling the JavaScript JSON.stringify() method. In a real-world app, the method would then send the JSON string to the server via Ajax. For this demo, we simply display the string in an alert box.

The stylesheet

To make our Widget Shop page look nice — and adapt to different screen sizes, from desktop down to mobile phone — we need to add a stylesheet. Save the following file as style.css in your widget-shop folder:

Try it out!

Click a product thumbnail, and notice how the chosen product's details appear at the bottom of the page. Try selecting product options by clicking the checkboxes under Customize Your Product, and entering different values in the Quantity field. Try selecting different products in the list. At any time, you can click the Buy Now button to see the JSON data that would be sent to the server.

Notice how various page elements — including the highlighting on the thumbnails and product options, the chosen product's details, and the price inside the Buy Now button — all update automatically as you interact with the widgets in the page. As you've seen, we've managed to do all this without writing any JavaScript code to update the DOM. Such is the magic of Knockout!

How Knockout works, and the concept of the Model-View-Viewmodel design pattern.

How to create a Knockout view (web page) and a view model object, and link the two together with bindings

How to use observables to create values in the view model that automatically update in the view, and vice-versa

How to use observable arrays to track a group of values at once

How to create computed observables to calculate values on the fly and create chains of dependent values

At the end of the tutorial, you brought all these concepts together and built a complete product selection page using Knockout, with a nice, interactive user interface that automatically adapts as the user selects different options.

I hope you enjoyed reading this tutorial, and found it useful. Have fun with Knockout!

Responses to this article

4 responses (oldest first):

Thanks for such a comprehensive article on Knockout...I'm currently checking out the various options with all these wonderful Javascript frameworks available. But one thing that has me stumped is how to integrate them with database's (receiving the data, updating the data etc...)Almost all of them say something like you have:"Normally this would be pulled dynamically from a database using a server-side script (such as PHP), but to keep things simple we'll create a static text file instead"But it seems difficult to find a real world example which demonstrates how this is done.Hope you can provide some feedback on this...Best Regards, Dave

@daveporter: Thanks for your comment. That's a good question. Essentially you'd have, for example, a MySQL database on the server, and a PHP script that runs a SELECT query on the DB to pull out the product data, then format it as a JSON string using http://php.net/manual/en/function.json-encode.php and send that back to the browser.

To go the other way, you'd use http://php.net/manual/en/function.json-decode.php to decode the JSON string that currently appears in the alert box when you press Buy Now, then do something useful with it (such as create a record in an 'orders' table etc).

Hard to summarise in a couple of paragraphs! Maybe I'll write an "end-to-end" tutorial explaining the process at some point...