Directive to Allow Decimal Numbers With a Single Decimal Point (.) Using AngularJS

This article explains how to create a Directive to allow decimal numbers with only a single decimal point (.) using AngularJS.

Introduction

In my previous article I explained How to Create a Directive to Allow Only Numbers Using AngularJs.

You often need to restrict the user to enter decimal numbers only but when you provide this functionality a major problem is encountered, the user can enter a decimal point (.) more than once in the TextBox and you encounter a medium bug. This article will provide the complete code to restrict users to decimal numbers with only a single decimal point allowed.

Step 1

First of all you need to add AngularJs and jQuery to your page, just like here:

2.     <title></title>
3.     <script src="angular.min.js"></script>
4.     <script src="jquery-1.11.1.min.js"></script>

You can either download them from my code that is available at the start of this article or you can download from their official websites.

Step 2

Now I am just adding a TextBox where I need to allow decimal numbers using a directive of AngularJs.

1. <body>
2.     <form ng-app="app" id="form1" runat="server">
3.         <div>
4.             <h3> Demo to Allow Decimal Numbers </h3>
5.             <hr />
6.              Provide Any Decimal Number: <input type="text"
7.                 name="AntiPer"
8.                 class="form-control"
9.                 allow-decimal-numbers />
10.             <hr />
11.         </div>
12.     </form>
13. </body>

Step 3

Now we need to work on the Angular code, the main part of this article.

1. <script>
2.     var app = angular.module('app', []);
3.     app.directive('allowDecimalNumbers'function () {
4.         return {
5.             restrict: 'A',
6.             link: function (scope, elm, attrs, ctrl) {
7.                 elm.on('keydown'function (event) {
8.                     var \$input = \$(this);
9.                     var value = \$input.val();
10.                     value = value.replace(/[^0-9\.]/g, '')
11.                     \$input.val(value);
12.                     if (event.which == 64 || event.which == 16) {
13.                         // numbers
14.                         return false;
15.                     } if ([8, 13, 27, 37, 38, 39, 40, 110].indexOf(event.which) > -1) {
16.                         // backspace, enter, escape, arrows
17.                         return true;
18.                     } else if (event.which >= 48 && event.which <= 57) {
19.                         // numbers
20.                         return true;
21.                     } else if (event.which >= 96 && event.which <= 105) {
22.                         // numpad number
23.                         return true;
24.                     } else if ([46, 110, 190].indexOf(event.which) > -1) {
25.                         // dot and numpad dot
26.                         return true;
27.                     } else {
28.                         event.preventDefault();
29.                         return false;
30.                     }
31.                 });
32.             }
33.         }
34.     });

Here first of all I created a module with the name "app", the module creation is a necessary part if you want to use Angular. This module is added to the HTML page using the ng-app directive.

After this I created the directive with the name "allowDecimalNumbers". If you are creating any kind of directive using AngularJs then you must always check that name of that directive should be provided using '-' at your HTML page and these dashes ("-") will be replaced by capital letters in the Angular code.

Since I had applied this directive on the attribute of the TextBox I had restricted this directive using "A", in other words Attriute.

I had applied this directive on the keydown event of the texbox.

These various conditions are applied to the ASCII values of the keys to allow or to stop them. You can see that a condition is added at the end that is allowing (46,110 and 190), this condition is used to allow the decimal point in the TextBox. In any case our ASCII values are not allowed by event.preventDefault() since it will remove that character and will revert back to the previous value.

But still the user is not restricted from entering the decimal point more than once. So, to remove this problem a small code is needed to be append in this directive as in the following:

1. var findsDot = new RegExp(/\./g)
2. var containsDot = value.match(findsDot)
3. if (containsDot != null && ([46, 110, 190].indexOf(event.which) > -1)) {
4.     event.preventDefault();
5.     return false;
6.

Here I am determining if our TextBox already has a decimal point, if it already has a decimal point and a another character is entered with an ASCII value that matches the ASCII value of a decimal point then event.preventDefault() will remove this new decimal point.

So now our directive looks as in:

1. app.directive('allowDecimalNumbers'function () {
2.     return {
3.         restrict: 'A',
4.         link: function (scope, elm, attrs, ctrl) {
5.             elm.on('keydown'function (event) {
6.                 var \$input = \$(this);
7.                 var value = \$input.val();
8.                 value = value.replace(/[^0-9\.]/g, '')
9.                 var findsDot = new RegExp(/\./g)
10.                 var containsDot = value.match(findsDot)
11.                 if (containsDot != null && ([46, 110, 190].indexOf(event.which) > -1)) {
12.                     event.preventDefault();
13.                     return false;
14.                 }
15.                 \$input.val(value);
16.                 if (event.which == 64 || event.which == 16) {
17.                     // numbers
18.                     return false;
19.                 } if ([8, 13, 27, 37, 38, 39, 40, 110].indexOf(event.which) > -1) {
20.                     // backspace, enter, escape, arrows
21.                     return true;
22.                 } else if (event.which >= 48 && event.which <= 57) {
23.                     // numbers
24.                     return true;
25.                 } else if (event.which >= 96 && event.which <= 105) {
26.                     // numpad number
27.                     return true;
28.                 } else if ([46, 110, 190].indexOf(event.which) > -1) {
29.                     // dot and numpad dot
30.                     return true;
31.                 } else {
32.                     event.preventDefault();
33.                     return false;
34.                 }
35.             });
36.         }
37.     }
38. });

Output

Now our application is created and we can check the output.

On running the application, a simple TextBox will be shown where decimal numbers are allowed.

If you press the numbers from anywhere in the key, they will be allowed but all the other characters except the decimal point will not be allowed to exist, even if they are special characters.

But if you try to enter more than one decimal point at any position in the TextBox then that decimal point will also not be allowed and will be removed.