Apply Extender Property Using KnokcoutJS in ASP.Net Application

Introduction

In today's article I will tell you how to apply an Extender Property using KnokcoutJS in an ASP.NET Application.

Observables allow the user to read/write values and show that value to the user but it might be possible that the user may want to add some new functionalities to the Observables. For that you need extenders. In this article Knockout Extenders Property will be used to create an application where we can convert the Value inserted to specific number of decimal points.

Step 1

First of all you need to add an external Knockout js file into your application, you can either download it from this link: "KnockoutJS" or can download my application available at the start of this article in Zip Format and then use the file attached with this Zip file.

After downloading the file you need to call it in the head section of your application.

<head runat="server">

    <title></title>

    <script src="knockout-2.3.0.js"></script>

</head>

Step 2

Now we can work on our application. First we will work on the ViewModel; for this you need to add a Script tag under the Body Section and then need to add this code:

        <script>

            ko.extenders.numeric = function (value, pointToDecimal) {

               

                var finalValue = ko.computed({

                    read: value, 

                    write: function (newValue) {

                        var current = value(),

                            roundingValue = Math.pow(10, pointToDecimal),

                            newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue),

                            valueAfterRound = Math.round(newValueAsNum * roundingValue) / roundingValue; 

 

                        if (valueAfterRound !== current) {

                            value(valueAfterRound);

                        } else {

 

                            if (newValue !== current) {

                                value.notifySubscribers(valueAfterRound);

                            }

                        }

                    }

                }).extend({ notify: 'always' });

                finalValue(value());

 

                return finalValue;

            };

 

            function x(one, two) {

                this.firstNumber = ko.observable(one).extend({ numeric: 0 });

                this.secondNumber = ko.observable(two).extend({ numeric: 2 });

            }

 

            ko.applyBindings(new x(221.2234, 123.4525));

        </script>

Here in the beginning I have used the extenders in which a function is created having a value and pointToDecimal as an argument. The first argument "value" is the observable itself. Then a computed function is used. In this computed function first we read the value, then I created a write function. In this write function some functionalities are taking place that are as in the following.

The roundingValue Math function is used to apply the pointToDecimal as a power of 10, that means that if pointToDecimal is given as 3 then roundingValue will apply 3 to 10 since it's power and it will return 1000 as it's value. We will provide the pointToDecimal by ourself in upcoming points.

Then in the valueAfterRound, newValueASNum is multiplied with the roundingValue and it's rounded value is devided with the roundingValue, so if the number was having four digits after the decimal point then they will be multiplied by 1000 that will provide a value that will have a single digit after the point, Math.round will convert this value to an integer value and divide this value with roundingValue, in other words 1000 will provide a final value that will have three digits after the point.

In the next step this value will be matched with the current value, if it's found to be not equal to the current value then it will be printed otherwise a notification will be shown.

We use:

.extend({ notify: 'always' });

when we want to delete the rejected values from the UI automatically. If we don't use this notify: "always" then it's possible that if the user enters a rejected value then there will be no notification shown and the same value will be shown in the newValue.

Then I created a function "x()", in this function two Observables are used named firstNumber and secondNumber. In both these Observables the ".extend()" function is used, .extend uses the extenders method in our Observables. In the extend function I provided the value as numeric: 0 and numeric: 2, this means that firstNumber will provide a number that will not have any type of decimal point so it will return a pure Integer number and secondNumber will return a value that will have a decimal point up to two numbers.

In the end I had applied the binding to the "x" and some default value is provided for both the first and second numbers.

The following is the complete code:

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title></title>

    <script src="knockout-2.3.0.js"></script>

</head>

<body>

    <form id="form1" runat="server">

    <div>

    <p><input data-bind="value: firstNumber" /> (provide only whole number)</p>

    <p><input data-bind="value: secondNumber" /> (round to two decimals)</p>

 

    </div>

        <script>

            ko.extenders.numeric = function (value, pointToDecimal) {

               

                var finalValue = ko.computed({

                    read: value, 

                    write: function (newValue) {

                        debugger;

                        var current = value(),

                            roundingValue = Math.pow(10, pointToDecimal),

                            newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue),

                            valueAfterRound = Math.round(newValueAsNum * roundingValue) / roundingValue;

 

        

                        if (valueAfterRound !== current) {

                            value(valueAfterRound);

                        } else {

 

                            if (newValue !== current) {

                                value.notifySubscribers(valueAfterRound);

                            }

                        }

                    }

                }).extend({ notify: 'always' });

 

                finalValue(value());

 

                return finalValue;

            };

 

            function x(one, two) {

                this.firstNumber = ko.observable(one).extend({ numeric: 0 });

                this.secondNumber = ko.observable(two).extend({ numeric: 2 });

            }

 

            ko.applyBindings(new x(221.2234, 123.4525));

        </script>

    </form>

</body>

</html>

Until now our work on ViewModel is completed so we can move forward to the View part of our application.

Step 3

In the View or Designer part use this code:

    <div>

    <p><input data-bind="value: firstNumber" /> (provide only whole number)</p>

    <p><input data-bind="value: secondNumber" /> (round to two decimals)</p>

 

    </div>

Here I took two Textboxes that are bound to the first and second number so they will show the values provided in the first and second Observables.

Output

First of all you will get an output like this one:

extend function knockout

As you can see that in the first TextBox only an Integer value is shown but the actual value has four digits after the decimal point and the second TextBox is showing the value with two digits after the decimal point.

Now if I make changes in the extend function of the Observable and change the numeric to some other value then the result will also change depending on these changes.

            function x(one, two) {

                this.firstNumber = ko.observable(one).extend({ numeric: 3 });

                this.secondNumber = ko.observable(two).extend({ numeric: 1 });

            }

extend function knockout

You can see that when I change the numeric to 3 and 1 then in the output window first TextBox is showing the value with three digits after the decimal places and the second TextBox is showing the value with one digit after the decimal value.


Similar Articles