Lion Foo
Lion Foo

Reputation: 37

Computed Observable Array from Observable Arrays

I am using Knockout to do something that I thought is simple. I am new to Knockout and JavaScript, therefore stuck. Any help will be greatly appreciated. Following is the problem at Hand.

I have three inventories of products (opening, closing, delivered) in the form of array and I want to compute the sold product inventory in the form of array. Actual data is bit complex. Here is the simplified version of my Data

var OpeningGasInventories = [{
  Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 1, 
  ShiftId: 1
}, {
 Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 2, 
  ShiftId: 1
}];

var ClosingGasInventories = [{
  Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 1, 
  ShiftId: 1
}, {
 Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 2, 
  ShiftId: 1
  }];


var DeliveredGasInventories = [{
  Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 1, 
  ShiftId: 1
}, {
 Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 2, 
  ShiftId: 1
  }];

 var SoldGasInventories = [{
  Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 1, 
  ShiftId: 1
}, {
 Id: 0,
  Volume: 0,
  TimeStamp: "0001-01-01T05:00:00Z",
  GasInventoryType: "Opening",
  GasProductId: 2, 
  ShiftId: 1
  }];

 var  GasProductSales= [{
  Id: 1,
  CashPrice: 1.919,
  CreditPrice: 0,
  VolumeCashSale: 0,
  VolumeCreditSale: 0,
  AmountCashSale: 0,
  AmountCreditSale: 0,
  GasProductId: 1,
  GasProductName: "Regular",
  ShiftId: 1
}, {
  Id: 2,
  CashPrice: 2.379,
  CreditPrice: 0,
  VolumeCashSale: 0,
  VolumeCreditSale: 0,
  AmountCashSale: 0,
  AmountCreditSale: 0,
  GasProductId: 2,
  GasProductName: "Premium",
  ShiftId: 1
}];

Following is my Knokcout code to compute Totals of each inventory and compute the sold inventory array

 var AppViewModel = function() {
 var self = this;

   self.OpeningGasInventories = ko.mapping.fromJS(OpeningGasInventories);
   self.ClosingGasInventories = ko.mapping.fromJS(ClosingGasInventories);
   self.DeliveredGasInventories =    ko.mapping.fromJS(DeliveredGasInventories);
  self.SoldGasInventories = ko.mapping.fromJS(SoldGasInventories);
  self.GasProductSales = ko.mapping.fromJS(GasProductSales);


 self.TotalOpeningGasInventory = ko.computed(function() {

        // Now calculate the sum of all Open Gas inventories
        var total = 0;
        self.OpeningGasInventories()
            .forEach(function(item, index) {
                total += +item.Volume() || 0;
            });

        return total.toFixed(0);
    });

    //Compute total of closing gas inventory
    self.TotalClosingGasInventory = ko.computed(function() {

        // Now calculate the sum of all Open Gas inventories
        var total = 0;
        self.ClosingGasInventories()
            .forEach(function(item, index) {
                total += +item.Volume() || 0;
            });

        return total.toFixed(0);
    });


    //Compute total of Delivered gas inventory
    self.TotalDeliveredGasInventory = ko.computed(function() {            
        var total = 0;
        self.DeliveredGasInventories()
            .forEach(function(item, index) {
                total += +item.Volume() || 0;
            });

        return total.toFixed(0);
    });

    //Compute total of Sold gas inventory
    self.TotalSoldGasInventory = ko.computed(function() {            
        var total = 0;           
        self.SoldGasInventories()
            .forEach(function(item, index) {
                console.info("Volume is " + item.Volume());
                total += +item.Volume() || 0;
            });           
        return total.toFixed(0);
    });

   self.SoldGasInventories = ko.computed(function() {            
        //we know all the four arrays are in same order and of same length 

        for (var i = 0; i < self.SoldGasInventories().length; i++) {                          

            self.SoldGasInventories()[i]
                .Volume = parseFloat(self.OpeningGasInventories()[i].Volume()) +
                parseFloat(self.DeliveredGasInventories()[i].Volume()) -
                parseFloat(self.ClosingGasInventories()[i].Volume());          

        }        

        return self.SoldGasInventories();
    });
 };

Issue: If I comment the last computed function self.SoldGasInventories then all the arrays totals are being computed fine.This last function suppose to computed the SoldGasInvetories array but it is not working as I would expect. Once I uncomment this function then the self.TotalSoldGasInventory does not get called. I have created a JSFIDDLE Please check and help me resolve my issue. Thanks a million..

Upvotes: 1

Views: 310

Answers (1)

Michael Best
Michael Best

Reputation: 16688

Your last computed doesn't return a computed value, but rather updates other observables.

self.UpdateSoldGasInventoriesVolumes = ko.computed(function() {
    //we know all the four arrays are in same order and of same length
    for (var i = 0; i < self.SoldGasInventories().length; i++) {
        self.SoldGasInventories()[i].Volume(
            parseFloat(self.OpeningGasInventories()[i].Volume()) +
            parseFloat(self.DeliveredGasInventories()[i].Volume()) -
            parseFloat(self.ClosingGasInventories()[i].Volume())
        );
    }
});

Upvotes: 1

Related Questions