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)

How dependency tracking works

Beginners don’t need to know about this, but more advanced developers will want to know why we keep making all these claims about KO automatically tracking dependencies and updating the right parts of the UI…

It’s actually very simple and rather lovely. The tracking algorithm goes like this:

  1. Whenever you declare a computed observable, KO immediately invokes its evaluator function to get its initial value.
  2. While the evaluator function is running, KO sets up a subscription to any observables (including other computed observables) that the evaluator reads. The subscription callback is set to cause the evaluator to run again, looping the whole process back to step 1 (disposing of any old subscriptions that no longer apply).
  3. KO notifies any subscribers about the new value of your computed observable.

So, Knockout doesn’t just detect dependencies the first time the evaluator runs - it redetects them every time. This means, for example, that the dependencies can vary dynamically: dependency A could determine whether the computed observable also depend on B or C. Then, it will only be re-evaluated when either A or your current choice of B or C changes. You don’t have to declare dependencies: they’re determined at runtime from the code’s execution. If the evaluator doesn’t access any obsevables, the computed observable will have no dependencies and won’t ever need to call the evaluator function again. In that case, to save resources, the computed observable will be automatically “disposed.”

The other neat trick is that declarative bindings are simply implemented as computed observables. So, if a binding reads the value of an observable, that binding becomes dependent on that observable, which causes that binding to be re-evaluated if the observable changes.

Pure computed observables work slightly differently. For more details, see the documentation for pure computed observables.

Controlling dependencies using peek

Knockout’s automatic dependency tracking normally does exactly what you want. But you might sometimes need to control which observables will update your computed observable, especially if the computed observable performs some sort of action, such as making an Ajax request. The peek function lets you access an observable or computed observable without creating a dependency.

In the example below, a computed observable is used to reload an observable named currentPageData using Ajax with data from two other observable properties. The computed observable will update whenever pageIndex changes, but it ignores changes to selectedItem because it is accessed using peek. In this case, the user might want to use the current value of selectedItem only for tracking purposes when a new set of data is loaded.

ko.computed(function() {
    var params = {
        page: this.pageIndex(),
        selected: this.selectedItem.peek()
    };
    $.getJSON('/Some/Json/Service', params, this.currentPageData);
}, this);

Note: If you just want to prevent a computed observable from updating too often, see the rateLimit extender.

Ignoring dependencies within a computed

The ko.ignoreDependencies function is available for scenarios where you want to execute code within a computed that should not contribute to that computed’s dependencies. This is often useful in a custom binding when you want to call code that may access observables, but you do not want to re-trigger the binding based on changes to those observables.

ko.ignoreDependencies( callback, callbackTarget, callbackArgs );

Example:

ko.bindingHandlers.myBinding = {
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var options = ko.unwrap(valueAccessor());
        var value = ko.unwrap(options.value);
        var afterUpdateHandler = options.afterUpdate;

        // the developer supplied a function to call when this binding updates, but
        // we don't really want to track any dependencies that would re-trigger this binding
        if (typeof afterUpdateHandler === "function") {
            ko.ignoreDependencies(afterUpdateHandler, viewModel, [value, color]);
        }

        $(element).somePlugin("value", value);
    }
}

Note: Why circular dependencies aren’t meaningful

Computed observables are supposed to map a set of observable inputs into a single observable output. As such, it doesn’t make sense to include cycles in your dependency chains. Cycles would not be analogous to recursion; they would be analogous to having two spreadsheet cells that are computed as functions of each other. It would lead to an infinite evaluation loop.

So what does Knockout do if you have a cycle in your dependency graph? It avoids infinite loops by enforcing the following rule: Knockout will not restart evaluation of a computed while it is already evaluating. This is very unlikely to affect your code. It’s relevant in two situations: when two computed observables are dependent on each other (possible only if one or both use the deferEvaluation option), or when a computed observable writes to another observable on which it has a dependency (either directly or via a dependency chain). If you need to use one of these patterns and want to entirely avoid the circular dependency, you can use the peek function described above.