Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my knockoutjs computed observable not working?

I can't seem to have a computed value of this working. any input would be appreciated.

i get the values for my prices from server.

 var pModel = function () {
     var self = this;
     self.prices = ko.observable({ "ID": 1,"Price1": 12,"Price2": 12});

     self.Total = ko.computed(function () {
         var total = 0;
         total = self.prices().Price1 + self.prices().Price2;
         return total;
     });
 };
 var VModel = new pModel();
 ko.applyBindings(VModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.1.0/knockout-min.js"></script>
<form action='/someServerSideHandler'>
    <table>
        <thead>
            <tr>Prices</tr>
        </thead>
        <tbody id="calc">
            <tr>
                <td>Price 1</td>
                <td>
                    <input data-bind='value: prices().Price1' />
                </td>
            </tr>
            <tr>
                <td>price 2</td>
                <td>
                    <input data-bind='value: prices().Price2' />
                </td>
            </tr>
            <td>TOTAL</td>
            <td> <span data-bind="text: $root.Total"></span>
            </td>
        </tbody>
    </table>
</form>
like image 871
NoviceDeveloper Avatar asked Mar 18 '13 17:03

NoviceDeveloper


2 Answers

Your prices variable is observable, but its members aren't. Redefine it like this:

 self.prices = ko.observable({
     ID: ko.observable(1),
     Price1: ko.observable(12),
     Price2: ko.observable(12)
 });

Now, this almost works, but if you change the values, it'll convert them to strings, so the total of 18 and 12 will be 1812! We'll need to turn those strings into numbers.

 self.Total = ko.computed(function () {
     var price1 = parseFloat(self.prices().Price1());
     var price2 = parseFloat(self.prices().Price2());
     return price1 + price2;
 });

You should be all set!

like image 69
Evan Hahn Avatar answered Sep 20 '22 15:09

Evan Hahn


You mixed things up a bit: Every value that other parts of your view model should be able to react on if changed must be an observable. In your case, you have an object "prices" which is an observable but the properties of this object (such as "Price1" and "Price2") are no observables. This means, that your computed observable would only be updated if the whole object placed in "prices" would be replaced by a new value.

So just make these values obserable:

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

    self.prices = {
        "ID": 1, // IDs normally do not change so no observable required here
        "Price1": ko.observable(12),
        "Price2": ko.observable(12)
    };

    self.Total = ko.computed(function () {
        return +self.prices.Price1() + +self.prices.Price2();
    });
};

Demo: http://jsfiddle.net/Jjgvx/3/

like image 44
Niko Avatar answered Sep 21 '22 15:09

Niko