knockout.js

Topics related to knockout.js:

Getting started with knockout.js

This section provides an overview of what knockout.js is, and why a developer might want to use it.

It should also mention any large subjects within knockout.js, and link out to the related topics. Since the Documentation for knockout.js is new, you may need to create initial versions of those related topics.

Bindings

What a binding is

Essentially a binding or a data binding is a way to link your ViewModels to your Views(templates) and vice versa. KnockoutJS uses two-way data binding, which means changes to your ViewModel influence the View and changes to your View can influence the ViewModel.

Under the hood (short overview)

Bindings are just plugins (scripts) that allow you to solve a particular task. This task is more often than not is changing markup (html) according to your ViewModel.

For example, a text binding allows you to display text and dynamically change it whenever your ViewModel changes.

KnockoutJS comes with many powerful bindings and lets you extend it with your own custom bindings.

And most importantly bindings are not magical, they work according to a set of rules and anytime you are unsure of what a binding does, what parameters it takes or when it will update the view you can refer to source code of the binding.

Consider the following example of a custom binding:

ko.bindingHandlers.debug = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        ko.computed(function () {
            var value = ko.unwrap(valueAccessor());
    
            console.log({
                value: value,
                viewModel: viewModel,
                bindingContext: bindingContext
            });
        }, null, { disposeWhenNodeIsRemoved: element });
    }
};
  1. A binding has a name - debug so you can use as follows:

data-bind="debug: 'foo'"

  1. The init method is called once when the binding is initiated. The rest of the updates are handled by a anonymous computed which is disposed when element is removed.
  2. The binding prints to console several things: the passed value in our example this value is foo (this value can also be observable since ko.unwrap method is used to read it), the current viewModel and bindingContext.
  3. Whenever the passed value changes the binding will print updated information to console.
  4. This binding cannot be used with virtual elements (in html comments), only on real elements, since ko.virtualElements.allowedBindings.debug flag is not set to true.

When to use parentheses

Without any additional plugins, KnockoutJS will only have live View updates for properties on the ViewModel that are observable (regular observable, but also computed, pureComputed, observableArray, etc). An observable would be created like this:

var vm = { name: ko.observable("John") };

In this case, vm.name is a function with two seperate "modes":

  1. Getter: vm.name(), without arguments, will get the current value;
  2. Setter: vm.name("Johnnyboy"), with an argument, will set a new value.

In the built-in data-bindings you can always use the getter form, and you can sometimes actually omit the parentheses, and the binding will effectively "add" them for you. So these are equivalent:

<p data-bind="text: name"></p> ... will work
<p data-bind="text: name()"></p> ... works too

But this will fail:

<p data-bind="text: 'Hello, ' + name + '!'"></p> ... FAILS!

Because as soon as you want to "do" something before passing a value to a data-binding, including value comparisons, you need to properly "get" the values for all observables, e.g.:

<p data-bind="text: 'Hello, ' + name() + '!'"></p> ... works

See also this Q&A for more details.

Equivalents of AngularJS bindings

Debugging a knockout.js application

Components introduction

Components allow reusable controls/widgets represented by their own view (template) and viewmodel. They were added in Knockout 3.2. Inspired by WebComponents, Knockout allows Components to be defined as Custom Elements, allowing the use of more self-explanatory markup.

Custom Bindings

Observables

Href binding

Working with knockout foreach binding with JSON

Bindings - Form fields

Bindings - Text and appearance

AJAX requests and binding