1

here am working on a snippet to get the calculations done using knockout and attached is the fiddle.

https://jsfiddle.net/naren_net/55etxj4y/272/

var vm = function() {
  this.PrevActualQty = ko.observable();
  this.PrevUnitCost = ko.observable();
  this.PrevTotalCost = ko.observable();

  this.ChangeQty = ko.observable(0);
  this.ChangeUnitCost = ko.observable(0);
  this.ChangeTotalCost = ko.observable(0);

  this.NewActualTotalCost = ko.observable(0);



  this.PrevTotalCost = ko.computed(function() {
    return (isNaN(this.PrevActualQty() * this.PrevUnitCost()) ? "" : this.PrevActualQty() * this.PrevUnitCost());
  }, this);

  this.NewActualQty = ko.computed(function() {
    return ((isNaN(this.PrevActualQty()) ? 0 : Number(this.PrevActualQty())) + (isNaN(this.ChangeQty()) ? 0 : Number(this.ChangeQty())));
  }, this);

  this.NewActualUnitCost = ko.computed(function() {
    return (isNaN(this.PrevUnitCost()) ? 0 : Number(this.PrevUnitCost()) + (isNaN(this.ChangeUnitCost()) ? 0 : Number(this.ChangeUnitCost())));
  }, this);

  this.NewActualTotalCost = ko.computed(function() {
    return (isNaN(this.NewActualQty()) ? 0 : Number(this.NewActualQty()) * (isNaN(this.NewActualUnitCost()) ? 0 : Number(this.NewActualUnitCost())));
  }, this);

  this.ChangeTotalCost = ko.computed(function() {
    return ((this.NewActualTotalCost()) - (this.PrevTotalCost()));
  }, this);

  this.ChangeTotalCost.subscribe(function(newValue) {
    alert(newValue);
  });

  this.Changed = function() {
    alert("fired");
    this.NewActualTotalCost(this.ChangeTotalCost() + this.PrevTotalCost());
  }
}


ko.applyBindings(new vm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table>
  <th>
    <td align=center>Qty</td>
    <td align=center>Unit Cost</td>
    <td align=center>Total Cost</td>
  </th>
  <tr>
    <td>Prev Actual</td>
    <td><input type=textbox data-bind='value:PrevActualQty' style='text-align:right'></td>
    <td><input type=textbox data-bind='value:PrevUnitCost' style='text-align:right'></td>
    <td><input type=textbox data-bind='value:PrevTotalCost()' style='text-align:right'></td>
  </tr>
  <tr>
    <td>Actual</td>
    <td align=right><input type=textbox data-bind='value:ChangeQty' style='text-align:right'></td>
    <td align=right><input type=textbox data-bind='value:ChangeUnitCost' style="text-align:right"></td>
    <td align=right><input type=textbox data-bind="value:ChangeTotalCost, event:{onchange:Changed}" , style="text-align:right"></td>

    <td><span data-bind="text:ChangeTotalCost"></span></td>
  </tr>
  <tr>
    <td>New Actual</td>
    <td align=right><span data-bind="text:NewActualQty"></span></td>
    <td align=right><span data-bind="text:NewActualUnitCost"></span></td>
    <td align=right><span data-bind="text:NewActualTotalCost"></span></td>
  </tr>
</table>

the issue is the onchange on the textbox with value:ChangeTotalCost doesnt fire. i want to capture the updated value and recalculate the value of NewActualTotalCost. is something wrong with the approach?

Thanks!


Thanks for the response! Actual is current data row that user can update, when user updates any of New Actual Row i.e Actual Qty / Actual Unit Cost / Actual Total Cost that should calculate the New Actual row data. all the three are computables, first 2 work fine, but the third(ChangeTotalCost) should update the NewActualTotalCost with PrevTotalCost + NewActualTotalCost and that should calculate the ActualUnitCost as (NewActualTotalCost /NewActualQty) - PrevActualUnitCost

1 Answers1

0

When knockout updates an input, there's no change event. Those events are only trigered by user interaction.

When working with <input> elements and knockout, you usually don't bind to a change event at all; you subscribe to the data-bound value instead!

Unfortunately, you'd create a circular dependency by doing so:

  1. ChangeTotalCost relies on NewActualTotalCost
  2. When ChangeTotalCost changes, you want the Changed method to update NewActualTotalCost
  3. Go back to 1, because a dependency changed

It's not entirely clear to me what your intended logic should be. If you can clarify the relation between the rows, I can help look for an alternative to the faulty event-based approach.

user3297291
  • 22,592
  • 4
  • 29
  • 45
  • I'm afraid your explanation doesn't make it any clearer for me. Might be nice to start out by a) removing all duplicate property declarations , b) making the computed inputs `readonly`, and c) replacing the `Number` parsing logic by a [numeric extender](https://stackoverflow.com/a/30371515/3297291) to make things a bit more readable. – user3297291 May 31 '18 at 14:48