Why is my knockoutjs computed observable not working?
Asked Answered
C

2

5

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>
Cathicathie answered 18/3, 2013 at 17:37 Comment(0)
B
4

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!

Building answered 18/3, 2013 at 17:49 Comment(2)
I am getting this: self.prices = ko.observable({ "ID": 1,"Price1": 12,"Price2": 12}); from server .. how can I make them observable if so?Cathicathie
The Knockout mapping plugin sounds like what you want.Building
F
3

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/

Fike answered 18/3, 2013 at 17:47 Comment(4)
You'll want to parseFloat on the prices before you compute the total, otherwise they'll combine strings.Building
I am getting this: self.prices = ko.observable({ "ID": 1,"Price1": 12,"Price2": 12}); from server .. how can I make them observable if so?Cathicathie
@Cathicathie Look into the mapping plugin: knockoutjs.com/documentation/plugins-mapping.htmlFike
will look into that.. your response actually appends the total instead of actually adding it.Cathicathie

© 2022 - 2024 — McMap. All rights reserved.