0
votes

Is it possible to have an object inside an observableArray that's a computed value of other observables within the same object? I have the following array:

self.drug_costs_table = ko.observableArray([
        {
            label: ko.observable('salad'),
            cost_per_dose: ko.observable('123'),
            administrations: ko.observable('9'),
            discount: ko.observable('10'),
            cost_per_year: ko.computed(function () {
                // administrations * cost per dose
            })
        }
]);

The observableArray will be built dynamically in the HTML and the final column is drug cost x administrations. Is it possible to have this value in the array or will something have to be done outside of the array to compute the cost_per_year?

This is my HTML:

<!-- ko foreach: drug_costs_table -->
    <div class="row">
        <div class="grid_4"><label data-bind="text: label"></label></div>
        <div class="grid_2"><input class="total-val" data-bind="decimal: cost_per_dose"></div>
        <div class="grid_2"><input data-bind="number: administrations"></div>
        <div class="grid_2"><input data-bind="percentage: discount"></div>
        <div class="grid_2"><input class="total-val" data-bind="decimal: cost_per_year"></div>
    </div>
<!-- /ko -->

Any help/advice on this would be greatly appreciated; I'm still a bit of a newbie to knockout!

Fiddle: http://jsfiddle.net/VWc8e/

2

2 Answers

4
votes

It is possible. But I think you will be better of defining a view model for the drug cost entity.

function drugCot(label, cost_per_does, administrations, discount) {
   var self = this;
    self.label = ko.observable(label),
    self.cost_per_dose = ko.observable(cost_per_does),
    self.administrations = ko.observable(administrations),
    self.discount = ko.observable(discount),
    self.cost_per_year = ko.computed(function () {
         return  self.administrations() *  self.cost_per_year();
    })
}

And then you can use it inside of your view model that contains self.drug_costs_table to add new costs.

self.durg_costs_table.push(new drugCost('salad', 123, 9, 10));

EDIT

Whenever you now update the self.administrations or self.cost_per_year observables your cost_per_year computed will be updated.

var drugCost1 = new drugCost('salad', 123, 9, 10);
self.durg_costs_table.push(drugCost1);
drugCost1.administrations(15);
// after this line of code cost_per_year will contian new value and will notify all the subscribers and rerender bound html elements
1
votes

Yes, it is possible to have have KO computed observables within a KO observable array. Nothing would have to be done outside of the array if the computed is only using other variables from the same object in the array.

self.drug_costs_table = ko.observableArray([
        {
            label: ko.observable('salad'),
            cost_per_dose: ko.observable('123'),
            administrations: ko.observable('9'),
            discount: ko.observable('10'),
            cost_per_year: ko.computed(function () {
                return parseInt(this.administrations(),10) * parseInt(this.cost_per_dose(),10);
            }, this)
        }
]);

Edit

The answer from @MyP3uK should be your preferred way of doing this