Getting started

  1. How KO works and what benefits it brings
  2. Downloading and installing

Observables

  1. Creating view models with observables
  2. Working with observable arrays

Computed observables

  1. Using computed observables
  2. Writable computed observables
  3. How dependency tracking works
  4. Pure computed observables
  5. Reference

Bindings

Controlling text and appearance

  1. The visible and hidden bindings
  2. The text binding
  3. The html binding
  4. The class and css bindings
  5. The style binding
  6. The attr binding

Control flow

  1. The foreach binding
  2. The if and ifnot bindings
  3. The with and using bindings
  4. The let binding
  5. The component binding
  6. Binding lifecycle events

Working with form fields

  1. The click binding
  2. The event binding
  3. The submit binding
  4. The enable and disable bindings
  5. The value binding
  6. The textInput binding
  7. The hasFocus binding
  8. The checked binding
  9. The options binding
  10. The selectedOptions binding
  11. The uniqueName binding

Rendering templates

  1. The template binding

Binding syntax

  1. The data-bind syntax
  2. The binding context

Creating custom bindings

  1. Creating custom bindings
  2. Controlling descendant bindings
  3. Supporting virtual elements
  4. Custom disposal logic
  5. Preprocessing: Extending the binding syntax

Components

  1. Overview: What components and custom elements offer
  2. Defining and registering components
  3. The component binding
  4. Using custom elements
  5. Advanced: Custom component loaders

Further techniques

  1. Loading and saving JSON data
  2. Extending observables
  3. Deferred updates
  4. Rate-limiting observables
  5. Unobtrusive event handling
  6. Using fn to add custom functions
  7. Microtasks
  8. Asynchronous error handling

Plugins

  1. The mapping plugin

More information

  1. Browser support
  2. Getting help
  3. Links to tutorials & examples
  4. Usage with AMD using RequireJs (Asynchronous Module Definition)

Components and Custom Elements - Overview

Components are a powerful, clean way of organizing your UI code into self-contained, reusable chunks. They:

  • …can represent individual controls/widgets, or entire sections of your application
  • …contain their own view, and usually (but optionally) their own viewmodel
  • …can either be preloaded, or loaded asynchronously (on demand) via AMD or other module systems
  • …can receive parameters, and optionally write back changes to them or invoke callbacks
  • …can be composed together (nested) or inherited from other components
  • …can easily be packaged for reuse across projects
  • …let you define your own conventions/logic for configuration and loading

This pattern is beneficial for large applications, because it simplifies development through clear organization and encapsulation, and helps to improve runtime performance by incrementally loading your application code and templates as needed.

Custom elements are an optional but convenient syntax for consuming components. Instead of needing placeholder <div>s into which components are injected with bindings, you can use more self-descriptive markup with custom element names (e.g., <voting-button> or <product-editor>). Knockout takes care to ensure compatibility even with old browsers such as IE 6.

Example: A like/dislike widget

To get started, you can register a component using ko.components.register (technically, registration is optional, but it’s the easiest way to get started). A component definition specifies a viewModel and template. For example:

ko.components.register('like-widget', {
    viewModel: function(params) {
        // Data: value is either null, 'like', or 'dislike'
        this.chosenValue = params.value;
        
        // Behaviors
        this.like = function() { this.chosenValue('like'); }.bind(this);
        this.dislike = function() { this.chosenValue('dislike'); }.bind(this);
    },
    template:
        '<div class="like-or-dislike" data-bind="visible: !chosenValue()">\
            <button data-bind="click: like">Like it</button>\
            <button data-bind="click: dislike">Dislike it</button>\
        </div>\
        <div class="result" data-bind="visible: chosenValue">\
            You <strong data-bind="text: chosenValue"></strong> it\
        </div>'
});

Normally, you’d load the view model and template from external files instead of declaring them inline like this. We’ll get to that later.

Now, to use this component, you can reference it from any other view in your application, either using the component binding or using a custom element. Here’s a live example that uses it as a custom element:

Source code: View

    <ul data-bind="foreach: products">
        <li class="product">
            <strong data-bind="text: name"></strong>
            <like-widget params="value: userRating"></like-widget>
        </li>
    </ul>

Source code: View model

    function Product(name, rating) {
        this.name = name;
        this.userRating = ko.observable(rating || null);
    }

    function MyViewModel() {
        this.products = [
            new Product('Garlic bread'),
            new Product('Pain au chocolat'),
            new Product('Seagull spaghetti', 'like') // This one was already 'liked'
        ];
    }

    ko.applyBindings(new MyViewModel());

In this example, the component both displays and edits an observable property called userRating on the Product view model class.

Example: Loading the like/dislike widget from external files, on demand

In most applications, you’ll want to keep component view models and templates in external files. If you configure Knockout to fetch them via an AMD module loader such as require.js, then they can either be preloaded (possibly bundled/minified), or incrementally loaded as needed.

Here’s an example configuration:

ko.components.register('like-or-dislike', {
    viewModel: { require: 'files/component-like-widget' },
    template: { require: 'text!files/component-like-widget.html' }
});

Requirements

For this to work, the files files/component-like-widget.js and files/component-like-widget.html need to exist. Check them out (and view source on the .html one) - as you’ll see, this is cleaner and more convenient that including the code inline in the definition.

Also, you need to have referenced a suitable module loader library (such as require.js) or implemented a custom component loader that knows how to grab your files.

Using the component

Now like-or-dislike can be consumed in the same way as before, using either a component binding or a custom element:

Source code: View

    <ul data-bind="foreach: products">
        <li class="product">
            <strong data-bind="text: name"></strong>
            <like-or-dislike params="value: userRating"></like-or-dislike>
        </li>
    </ul>
    <button data-bind="click: addProduct">Add a product</button>

Source code: View model

    function Product(name, rating) {
        this.name = name;
        this.userRating = ko.observable(rating || null);
    }

    function MyViewModel() {
        this.products = ko.observableArray(); // Start empty
    }

    MyViewModel.prototype.addProduct = function() {
        var name = 'Product ' + (this.products().length + 1);
        this.products.push(new Product(name));
    };

    ko.applyBindings(new MyViewModel());

If you open your browser developer tools’ Network inspector before your first click on Add product, you’ll see that the component’s .js/.html files are fetched on demand when first required, and thereafter retained for reuse.

Learn more

More more detailed information, see: