What is Computed Observable in Knockout.js?

In this article we will have a look at a Computed Observable in Knockout.js. Let us start with an example, you have a ViewModel as in the following:

var viewModel =
{
   nameko.observable("G Block"),
   ageko.observable(40)
};


Now you want a custom message to be rendered on the view, that message will depend on other observables of ViewModel. To create that custom message you need to create a Computed Observable. A Computed Observable can be created as in the following:

Computed Observable

It takes the following two parameter:

  1. The first parameter is a function. The function will work with other observables and calculate the Computed Observable
  2. The second parameter is the name of the function. If you are creating a Computed Observable inside the ViewModel then the second parameter should be this.

So a ViewModel with a Computed Observable is as follows:

 var viewModel =
{
     nameko.observable("G Block"),
     ageko.observable(40),           
};
viewModel.greet = ko.computed(function () {
return this.name()
    + " is " +
    this.age() +" years old";
}, viewModel);     
ko.applyBindings(viewModel);

The view binding can be done as follows:

<input type="text" data-bind="value:name" />
<input type="text" data-bind="value:age" /> <br />
<span data-bind="text:greet" />


A few points worth knowing about Computed Observable are:

  • It gets evaluated as soon as the Computed Observable is created. So we may get into a problem in a scenario in which a Computed Observable is based on properties that are not yet computed or initialized or loaded.
  • If the Computed Observable is based on a simple property (not an observable property) then a change in property will not trigger a change in Computed Observable
  • A change in Computed Observable is triggered if any of the observable properties that it is based on is changed.

A Computed Observable can be created in one more way as well. You can create a ViewModel as in the following:

function viewModel() {
 var self = this;
  self.name = ko.observable("G Block");
  self.age = ko.observable(40);
  self.greet = ko.computed(function () {
  return self.name()
  + " is " +
  self.age() +
  " years old";
   }, this);
};


Note that we have added a Computed Observable as part of the ViewModel. If you follow this way of creating a ViewModel then you need to manage this explicitly. We are passing a second parameter as "this". Without passing it we can’t evaluate the Computed Observable and cannot access other observables to calculate the Computed Observable. So if you don’t pass this as the second parameter then you won’t be able to access this.age() and this.name(). In the scenario above we are preserving this in "self" inside the ViewModel and using "self" instead of this.

Writeable Computed Observable

So far we have created a Computed Observable reading values of other observables and then returning the value based on them. These observables are Read-Only Computed Observables.

You can create a writeable Computed Observable as well. You might wish to create a writeable Computed Observable in any of the following possible scenarios.

  1. Interpreting user input
  2. Validating user input
  3. Setting values of other observables based on some logic

So let us see how to use a writeable Computed Observable. Let us say you have a view as below:

writeable computed observable
The requirements are:

  1. When you change run Average should be updated.
  2. The Average is a Computed Observable and based on Runs and Match

We can do the requirement above by creating a simple ViewModel and a read only Computed Observable.

One of other requirements is that when you change Average, Runs should be updated. This can be done by creating a Writeable Observable.

Let us start by creating a ViewModel as in the following:

var playerViewModel =
        {
            nameko.observable("Sachin T"),
            runsko.observable(10000),
            matchko.observable(100)
        };

Now we need to create a writeable Computed Observable.

 playerViewModel.average = ko.computed({
readfunction ()
{
       var avg = this.runs() / this.match();
       return avg;
},
writefunction (value)
{
   var r = value * this.match();
   this.runs(r);

 },
    ownerplayerViewModel
});


To create a writeable Computed Observable:

  1. You need to pass a JavaScript object to the ko.computed function
  2. That takes options like read, write, owner and so on.
  3. The Read property takes a function and returns a value based on other observables
  4. The Write property also takes a function as input. This function takes an input parameter “value”. You may wish to perform operations on the value and write back the resulting value to another observable.
  5. You need to have the ViewModel as the owner. This defines the reference of the key

viewModel 

In this way you can create a writeable Computed Observable. You can bind values to the View as below:

<span data-bind="text:name"></span> <br />
   Runs: <input type="text" data-bind="value:runs" /> <br />
   Match: <input type="text" data-bind="value:match" /> <br />
   Average:  <input type="text" data-bind="value:average" />


Deferred Evaluation of Computed Observable

Before we end this article let us explain one more concept of deferred execution of a Computed Observable. As we explained in the beginning of this post that Computed Observable is evaluated at the time of creation. So if it is based on an observable that is not loaded when the Computed Observable is created then you might have a problem. KO gives you the option to deferr execution of a Computed Observable. You can do that by setting the deferEvaluation value to true

 
Deferred Evaluation
We learned in this post about Computed Observables. I hope you find this post useful. Thanks for reading.

Up Next
    Ebook Download
    View all
    Learn
    View all