0

I have an object returned from a ajax call and from this object I want to do some calculations on it, depending on inputs from the user. Inputs being a number input and checkbox to include another figure in the calculation or not.

My JS is:

var viewModel = function() 
{
        var self = this;
    self.currentVal = ko.observable(2);
    self.includeTax = ko.observable(false);
    self.sales = ko.observableArray([]);
    self.computedSales = ko.observableArray([]);

self.sales([
    {"ProductID": "10121a", "Cost": 110, "Quantity": 6, "X": 9034.25, "Other": 23, "Date": 2017-05-5}, 
    {"ProductID": "10122b", "Cost": 10, "Quantity": 18, "X": 152.99, "Other": 20, "Date": 2017-05-3},
    {"ProductID": "10123c", "Cost": 1000, "Quantity": 2, "X": 99.50, "Other": 5, "Date": 2017-05-1}]);

self.computeSales = function() {
    ko.utils.arrayForEach(self.sales(), function (item) {
    self.computedSales().push({
        "ProductID": item.ProductID, 
      "Total": item.Cost * item.Quantity,
      // "Total" is needed for the Calc value, is there a way to re-use the Total without having to duplicate it below?:
      // "Calc": item.Cost * item.Quantity * (self.currentVal / 100)
      "Calc": self.includeTax() == true ? (item.Cost * item.Quantity * (2 / 100) * .5) : (item.Cost * item.Quantity * 2 / 100)
      });

      //alert(self.computedSales()[self.computedSales().length -1].Total);
  });
  // self.currentVal not correct:
  //alert(self.currentVal);
};
self.computeSales();
};

$(function () {
    ko.applyBindings(new viewModel());
});

The Calc column does not change when I tick the checkbox nor change the value in the input - what am I doing wrong?

My main aim was to find a way to re-use some of the properties such as Total, instead of having to duplicate item.Cost * item.Quantity, but I guess this is another separate question.

Fiddle

Any help appreciated!

1 Answer 1

3

I think this would be easier if your sales objects were actually strongly typed objects that you could attach a computed to. Firstly, you should create an object for your sales:

var sale = function(item) {
    var thisSale = this;
    thisSale.productId = ko.observable(item.ProductID);
    thisSale.cost = ko.observable(item.Cost);
    thisSale.quantity = ko.observable(item.Quantity);
    //etc with all properties needed.
    thisSale.calc = ko.pureComputed(function() {
        return self.includeTax() == true ? (thisSale.Cost * thisSale.Quantity * (2 / 100) * .5) : (thisSale.Cost * thisSale.Quantity * 2 / 100)
    });
}

Then create these objects with your data:

self.computeSales = function() {
    ko.utils.arrayForEach(self.sales(), function (item) {
        self.computedSales().push({
            new sale(item);
        });
    });
};

A computed value will update whenever an observable that it references updates so by making the calc a computed value you should be able to have it updated when the checkbox is altered. Apologies if this isn't very clear and I haven't tested this code at all so you may need to tweak it but the general principle should be there!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.