0

I have a simple table with two input columns bound to a view model (vm). Say one of the properties is vm.ColA and the other is vm.ColB.

There are a number of other columns, so I have used

ko.mapping.fromJS(data, {}, this);

to create observables for each property. However, ColA and ColB must be able to take input, and when they do, influence the other. For example, say there is a Factor property such that (ColA * Factor = ColB) and (ColA = ColB / Factor).

I need to be able to enter a value in ColA and have it calculate ColB, but if I enter a value in ColB, it should calculate ColA.

I have looked at writeable computed observables, but so far, I have not been able to find an example or a discussion about two properties that would influence each other this way.

Kelly Cline
  • 2,206
  • 2
  • 33
  • 57
  • http://stackoverflow.com/questions/30717905/how-can-i-get-two-computed-values-to-bind-to-each-other – Roy J Dec 18 '15 at 00:12

1 Answers1

0

To implement this kind of dependency you need to explicitly subscribe to colAto modify colB value when it changes, and viceversa.

colA.subscribe(function(newValue) {
    colB( /* calculation based upon colA newvalue */);
});

The problem is tha as colA depends on colB and viceversa you can enter an infinite loop (unless the calculations are exact, and the values doesn't change when doing the calculations, which is not guarranteed). I.e. when you change colA the subscription changes colB, whose subscription, in turn, changes colA, and so on.

To avoid this recursion, you can implement a solution like this: Change observable but don't notify subscribers in knockout.js or something similar. The question is that when colA changes colB, colA should not be notified by colB change.

Another possible solution is to check that the result of the calculation is approximately equal to the value in the other observable, and,in that case, you don't change it to break the loop. I.e. if the result of calculating colB when colA changes is approximately equal to the value in colB, you don't change the value in colB.

halfer
  • 19,824
  • 17
  • 99
  • 186
JotaBe
  • 38,030
  • 8
  • 98
  • 117