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 binding
  2. The text binding
  3. The html binding
  4. The css binding
  5. The style binding
  6. The attr binding

Control flow

  1. The foreach binding
  2. The if binding
  3. The ifnot binding
  4. The with binding
  5. The component binding

Working with form fields

  1. The click binding
  2. The event binding
  3. The submit binding
  4. The enable binding
  5. The disable binding
  6. The value binding
  7. The textInput binding
  8. The hasFocus binding
  9. The checked binding
  10. The options binding
  11. The selectedOptions binding
  12. 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

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. Rate-limiting observables
  4. Unobtrusive event handling
  5. Using fn to add custom functions
  6. Extending Knockout's binding syntax

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)

Adding custom functions using "fn"

Occasionally, you may find opportunities to streamline your code by attaching new functionality to Knockout’s core value types. You can define custom functions on any of the following types:

Because of inheritance, if you attach a function to ko.subscribable, it will be available on all the others too. If you attach a function to ko.observable, it will be inherited by ko.observableArray but not by ko.computed.

To attach a custom function, add it to one of the following extensibility points:

  • ko.subscribable.fn
  • ko.observable.fn
  • ko.observableArray.fn
  • ko.computed.fn

Then, your custom function will become available on all values of that type created from that point onwards.

Note: It’s best to use this extensibility point only for custom functions that are truly applicable in a wide range of scenarios. You don’t need to add a custom function to these namespaces if you’re only planning to use it once.

Example: A filtered view of an observable array

Here’s a way to define a filterByProperty function that will become available on all subsequently-created ko.observableArray instances:

ko.observableArray.fn.filterByProperty = function(propName, matchValue) {
    return ko.pureComputed(function() {
        var allItems = this(), matchingItems = [];
        for (var i = 0; i < allItems.length; i++) {
            var current = allItems[i];
            if (ko.unwrap(current[propName]) === matchValue)
                matchingItems.push(current);
        }
        return matchingItems;
    }, this);
}

This returns a new computed value that provides a filtered view of the array, while leaving the original array unchanged. Because the filtered array is a computed observable, it will be re-evaluated whenever the underlying array changes.

The following live example shows how you could use this:

All tasks ( )

Done tasks ( )

Source code: View

<h3>All tasks (<span data-bind="text: tasks().length"> </span>)</h3>
<ul data-bind="foreach: tasks">
    <li>
        <label>
            <input type="checkbox" data-bind="checked: done" />
            <span data-bind="text: title"> </span>
        </label>
    </li>
</ul>

<h3>Done tasks (<span data-bind="text: doneTasks().length"> </span>)</h3>
<ul data-bind="foreach: doneTasks">
    <li data-bind="text: title"></li>
</ul>

Source code: View model

function Task(title, done) {
    this.title = ko.observable(title);
    this.done = ko.observable(done);
}

function AppViewModel() {
    this.tasks = ko.observableArray([
        new Task('Find new desktop background', true),
        new Task('Put shiny stickers on laptop', false),
        new Task('Request more reggae music in the office', true)
    ]);

    // Here's where we use the custom function
    this.doneTasks = this.tasks.filterByProperty("done", true);
}

ko.applyBindings(new AppViewModel());

It’s not mandatory

If you tend to filter observable arrays a lot, adding a filterByProperty globally to all observable arrays might make your code tidier. But if you only need to filter occasionally, you could instead choose not to attach to ko.observableArray.fn, and instead just construct doneTasks by hand as follows:

this.doneTasks = ko.pureComputed(function() {
    var all = this.tasks(), done = [];
    for (var i = 0; i < all.length; i++)
        if (all[i].done())
            done.push(all[i]);
    return done;
}, this);