knockout.js Bindings

Help us to keep this website almost Ad Free! It takes only 10 seconds of your time:
> Step 1: Go view our video on YouTube: EF Core Bulk Extensions
> Step 2: And Like the video. BONUS: You can also share it!

Syntax

  • <!-- ko if:myObservable --><!-- /ko -->
  • <i data-bind="if:myObservable"></i>

Remarks

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.



Got any knockout.js Question?