Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
KnockoutJS Web Development

You're reading from   KnockoutJS Web Development Efficiently work with data, web templates, and custom HTML tags using KnockoutJS

Arrow left icon
Product type Paperback
Published in Feb 2015
Publisher
ISBN-13 9781782161028
Length 178 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
John Farrar John Farrar
Author Profile Icon John Farrar
John Farrar
Arrow right icon
View More author details
Toc

Automating calculations with Knockout

In this section, we will take functions to a deeper level.

In the code bundle of chapter 1 do folder (/ko_1/do/), copy the base.htm file as computed.htm for this segment. After the leading body tag, put in the following View code:

<table>
    <tr>
        <th style="width:20%;">
            Item
        </th>
        <th style="width:40%;">
            Qty
        </th>
        <th>
            Price
        </th>
        <th>
            Tally
        </th>
    </tr>
    <tr>
        <td style="width:20%;">
            <em data-bind="text:item_1">Item</em>
        </td>
        <td style="width:40%;">
            <input type="text" data-bind="value:qty_1" />
        </td>
        <td>
            <span data-bind="text:price_1"></span>
        </td>
        <td>
            <span data-bind="text:tally_1"></span>
        </td>
    </tr>
</table>

Now we are ready to create the scripted side of the Knockout ViewModel code. Place this code inside the script tag after the KnockoutJS library is included:

calcModel = function(){
    var self = this;
    self.item_1 = ko.observable('Cell Phone');
    self.qty_1 =  ko.observable(0);
    self.price_1 = ko.observable(149.95);
    self.tally_1 = ko.computed(function(){
        var rslt = (+self.qty_1() * self.price_1()).toFixed(2);
        return rslt;
    },self);
}
vm = new calcModel();
ko.applyBindings(vm);

Notice that the computed function is now doing live calculations. We also added a fixed decimal position of two places. Enter a quantity to test:

Automating calculations with Knockout

Create a second row of the table and the ViewModel that matches the features of the first row. I want you to create this on your own to make sure you are getting the skills as you go along here. You could, of course, peek at the example in the done folder, but you should try it on your own first.

Subtotal calculation

Now add this row to the bottom of the table to create a row for the subtotal. You can also see we created a cell in the table to tally the number of items in qty_1 and qty_2:

<tr>
    <td style="width:20%;">
        &nbsp;
    </td>
    <td style="width:40%;">
        <span data-bind="text:t_qty"></span>
    </td>
    <td>
        <em>subTotal</em>
    </td>
    <td>
        <span data-bind="text:subTotal"></span>
    </td>
</tr>

You also need to put the script code into the correct locations:

    self.item_2 = ko.observable('Cell Case');
    self.qty_2 = ko.observable(0);
    self.price_2 = ko.observable(19.45);
    self.tally_2 = ko.computed(function(){
        var rslt = (+self.qty_2() * self.price_2()).toFixed(2);
        return rslt;
    },self);
    self.t_qty = ko.computed(function(){
        return +(self.qty_1()) + +(self.qty_2());
    },self);
    self.subTotal = ko.computed(function(){
        var rslt = (+(self.tally_1()) + +(self.tally_2())).toFixed(2);
        return rslt;
    });

You may have noticed that we placed an extra + before some of the variables. This is a standard JavaScript approach to making sure the number entered into the input box comes out as a number. In some browsers and some conditions the number is the string representation of the number. The addition of + solves this issue.

Now run the page and enter the quantity to ensure that all of your calculations are working:

Subtotal calculation

Tax time

What fun would buying things be without paying taxes? Well, either way it is a function we all need to get right. Add the following code to the table to have a row for taxes:

    <tr>
        <td style="width:20%;">
            &nbsp;
        </td>
        <td style="width:40%;">
            ( rate  in decimal <input data-bind="value: taxRate;" /> )
        </td>
        <td>
            <em>Tax</em>
        </td>
        <td>
            <span data-bind="text:taxed"></span>
        </td>
    </tr>

Now add the code here to the script section of the page to make our ViewModel run smartly. Our goal is not to write the most efficient code in all of the world but rather to expose you to learning to think the Knockout way:

    self.tax = ko.observable(.05);
    self.taxed = ko.computed(function(){
        return +(self.subTotal()*self.tax()).toFixed(2);
    });
    self.taxRate = ko.computed({
        read: function(){
            return self.tax()*100 + '%';
        },
        write: function(value){
            value = parseFloat(value.replace(/[^\.\d]/g, ""));
            self.tax(+value/100);
        }
    });

If we were coding the page with standard JavaScript or even with jQuery to get the amount of functionality we have achieved, it would take many multiples of the code we have on the page here. This approach is far more elegant and much smaller.

Notice how our taxRate is done just a little differently. Calculation functions in Knockout can read and write. You can also call other external resources because it is standard script code. Note that in our scripted code we have to place the values in parentheses to do the assignments as we did to the tax value.

You should also notice that we are converting the value in and out of decimal format and adding a percentage to the displayed value of the taxes in the input box. It also smartly strips the percent mark off if you enter it when updating the tax rate.

Tip

Regular expressions like the one used in our write method are a way to supercharge your apps. Make it a point to learn at least basic regular expressions. If you do not know how to do the advanced stuff, you can often find what you need either in a Google search, or some "happy guru" will volunteer to assist you with a winning answer in some online forum.

Refresh the page with the updates, and you will see that even the actual tax amount has been calculated in the Tally column:

Tax time

Final total

Here we have the final segment of the View code for our calculation example:

<tr>
    <td style="width:20%;">
        &nbsp;
    </td>
    <td style="width:40%;">
        &nbsp;
    </td>
    <td>
        <em>Total</em>
    </td>
    <td>
        <span data-bind="text:total"></span>
    </td>
</tr>

The last piece of script code should be added to the ViewModel. There is nothing fancy about this section of code other than its ability to complete our functionality. We add in the value of the taxed item here, and again, we wrap the numbers with a parentheses and use the toFixed function to set the answer to two decimal places.

    self.total = ko.computed(function(){
        var rslt = (+self.subTotal() + self.taxed()).toFixed(2);
        return rslt;
    });

Now we can run the code and play with the entry boxes to see that everything is working as expected. For new developers, it may not surprise you to see how little code it takes to make a page like this work. It used to take so much code that hardly anyone anywhere would take the time to attempt building tools like this. It was compounded because things worked differently from one browser to the next. While this is still true, libraries like Knockout remove many of those pains and let us concentrate on the results instead of the platforms.

Running the code now should give us results similar to this screen capture:

Final total
You have been reading a chapter from
KnockoutJS Web Development
Published in: Feb 2015
Publisher:
ISBN-13: 9781782161028
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime