Wednesday, March 1, 2017

KnockoutJS - Dependency Tracking

Dependency Tracking in KnockoutJS

KnockoutJs automatically tracks the dependencies when the values get updated. It has a single object called dependency tracker(ko.dependencyDetection) which acts as an intermediate between two parties for subscribing the dependencies.
The algorithm for dependency tracking can be shown as below:

dependency tracking
  • Whenever you declare a computed observable, KO immediately invokes its evaluator function to get its initial value.
  • Subscription is set up to any observable that evaluator reads. In an application, the old subscriptions which are no longer used are disposed.
  • KO finally notifies the updated computed observable.

Example

<!DOCTYPE html>
<html>
   <head>
       <title>KnockoutJS How Dependency Tracking Works</title>
         <!-- CDN's-->
         <script src="https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" type="text/javascript"></script>
   </head>
   <body>
      <div>
         <form data-bind="submit: addFruits">
            <b>Add Fruits:</b>
            <input data-bind='value: fruitToAdd, valueUpdate: "afterkeydown"'/>
            <button type="submit" data-bind="enable: fruitToAdd().length > 0">Add</button>
            <p><b>Your fruits list:</b></p>
            <select multiple="multiple" width="50" data-bind="options: fruits"> </select>
        </form>
      </div>
      <script>
         var Addfruit = function(fruits) {
            this.fruits = ko.observableArray(fruits);
            this.fruitToAdd = ko.observable("");
            this.addFruits = function() {
               if (this.fruitToAdd() != "") {
                  this.fruits.push(this.fruitToAdd()); // Adds a fruit
                  this.fruitToAdd(""); // Clears the text box
                }
            }.bind(this); // "this" is the view model
         };

         ko.applyBindings(new Addfruit(["Apple", "Orange", "Banana"]));
      </script>
   </body>
</html>

Output

Let's carry out the following steps to see how the above code works:
  • Save the above code in dependency_tracking.htm file.
  • Open this HTML file in a browser.
  • Enter any fruit name and click on Add button.

Controlling Dependencies Using Peek

The Computed Observable can be accessed without creating a dependency, by using the peek function. It controls the ' Observable by updating the computed property.

Example

<!DOCTYPE html>
<html>
   <head>
       <title>KnockoutJs Controlling Dependencies Using Peek</title>
           <!-- CDN's-->
       <script src="https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.1.0.js" type="text/javascript"></script>
   </head>
   <body>
        <div class="logblock">
           <h3>Computed Log</h3>
           <pre class="log" data-bind="html: computedLog"></pre>
        </div>

        <script>
          function AppData() {
             this.firstName = ko.observable('John');
             this.lastName = ko.observable('Burns');
             this.computedLog = ko.observable('Log: ');
             this.fullName = ko.computed(function () {
                 var value = this.firstName() + " " + this.lastName();
                 this.computedLog(this.computedLog.peek() + value + '; <br/>');
                 return value;
              }, this);

             this.step = ko.observable(0);
                this.next = function () {
                this.step(this.step() === 2 ? 0 : this.step()+1);
             };
          };
          ko.applyBindings(new AppData());
      </script>
   </body>
</html>

Output

Let's carry out the following steps to see how the above code works:
  • Save the above code in dependency_tracking_peek.htm file.
  • Open this HTML file in a browser.

Observations

Ignoring dependencies within a computed

The ko.ignoreDependencies function helps ignore the dependencies the ones you don't want to track within the computed dependencies. Following is its syntax:
ko.ignoreDependencies( callback, callbackTarget, callbackArgs );

Why circular dependencies aren't meaningful

If KO is evaluating a Computed Observable then it will not restart an evaluation of the dependent Computed Observable. Hence it doesn't make sense to include cycles in your dependency chains.

No comments:

Post a Comment