Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force a computed property function to run

Given a computed property

vm.checkedValueCount = ko.computed(function(){   var observables = getCurrentValues();  //an array of ko.observable[]   return _.filter(observables, function(v) { return v() }).length; }); 

suppose getCurrentValues() can return different sets of observables which are modified elsewhere in the code (and comes from a more complex structure than an observableArray).

I need checkedValueCount to update whenever

  • one of its dependencies change
  • getCurrentValues() returns a different set of observables.

The problem is that ko.computed seems to memoize the last returned value and only update when a dependency updates. This handles the first case but not the latter.

What I'm looking for is a way to force checkedValueCount to re-run. Something which I can use like:

changeCurrentValues(); vm.checkeValueCount.recalculate(); 

Put most simply, given that I have

a = ko.computed(function() { return Math.random() }) 

how can I force invoking a() twice to return different values.

like image 817
George Mauer Avatar asked Dec 07 '12 19:12

George Mauer


People also ask

Can we pass parameters to computed property?

No, you can't pass parameters to computed properties.

Can a computed property be async?

This feature is synchronous. However, the vue-async-computed package allows you to create and consume asynchronous computed properties in your components by binding the resolved value of a Promise to a component property.

Can we call a method in computed property?

Computed Caching vs MethodsInstead of a computed property, we can define the same function as a method. For the end result, the two approaches are indeed exactly the same. However, the difference is that computed properties are cached based on their reactive dependencies.

Can you set a computed property?

Computed properties are getter-only by default, but if you need to, you can also specify a setter. To do this, we actually need to change our computed property from a function to an object with two properties; get and set.


2 Answers

I realized my first answer missed your point, and won't solve your issue.

The problem is that a computed will only reevaluate if there is some observable that forces it to re-evaluate. There is no native way to force a computed to re-evaluate.

However, you can get around this with some hackery by creating a dummy observable value and then telling its subscribers that it has changed.

(function() {      var vm = function() {         var $this = this;          $this.dummy = ko.observable();          $this.curDate = ko.computed(function() {             $this.dummy();             return new Date();         });          $this.recalcCurDate = function() {             $this.dummy.notifySubscribers();         };             };      ko.applyBindings(new vm());  }());​ 

Here is a Fiddle showing this approach

like image 53
Josh Avatar answered Oct 21 '22 22:10

Josh


There is a method to force recalculation of all observables depending on yours:

getCurrentValues.valueHasMutated() 
like image 28
Rustam Avatar answered Oct 21 '22 21:10

Rustam