Skip to content Skip to sidebar Skip to footer

Why Does A Function In A Child View Model Causes A Computed In The Parent View Model To Fire?

Pushing the button in the following code does 2 things: It executes a function in a nested view model, and also makes a computed in the parent view model to execute. However, if

Solution 1:

As an addition to the accepted answer, I'm posting here the relevant parts of the documentation:

How dependency tracking works

[...]

It’s actually very simple and rather lovely. The tracking algorithm goes like this:

  1. Whenever you declare a computed observable, KO immediately invokes its evaluator function to get its initial value.
  2. While the evaluator function is running, KO sets up a subscription to any observables (including other computed observables) that the evaluator reads. The subscription callback is set to cause the evaluator to run again, looping the whole process back to step 1 (disposing of any old subscriptions that no longer apply).
  3. KO notifies any subscribers about the new value of your computed observable.

If you'd like to prevent a dependency creation, use peek:

Knockout’s automatic dependency tracking normally does exactly what you want. But you might sometimes need to control which observables will update your computed observable, especially if the computed observable performs some sort of action, such as making an Ajax request. The peek function lets you access an observable or computed observable without creating a dependency.

So the given code will be changed into:

varMasterViewModel = function () {
  var self = this;
  self.nested = newFirstViewModel();
  self.func = ko.computed (function() {
    var items = self.nested.array.peek();
    alert("executed");
  });
}
varFirstViewModel = function () {
  var self = this;
  self.array = ko.observableArray([]);
  self.push = function () {
    self.array.push(newSecondViewModel());
    alert("pushed");
  }
}

varSecondViewModel = function () {
  var self = this;
  self.z = ko.observable();
}

var mvm = newMasterViewModel();
ko.applyBindings(mvm);
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script><divdata-bind="value: func"><divdata-bind="with: nested"><buttondata-bind="text: 'push me', click: push"></button></div></div>

Note that now, when pushing the button, only an alert of "pushed" is displayed.

Solution 2:

First: The data-bind="func" in <div data-bind="func"> raises a red flag for me. Normally a binding is in the form bindingName: boundValue.

But answering the question: A computed's value is recomputed whenever any of the observables it depends on is changed. You're changing self.array in FirstViewModel#push, so naturally the value of the computed that uses it in MasterViewModel (as self.nested.array) is recomputed.

Post a Comment for "Why Does A Function In A Child View Model Causes A Computed In The Parent View Model To Fire?"