Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular directive: Allow just numbers

Here is a sample angular directive to prevent typing non-numeric keys (StackOverflow answer). I want to write something like this fiddle to use the is-number directive in several inputs. Please consider that since I have various different directives in my inputs, I cannot use the same template as suggested in the update of mentioned answer above.

var $scope;
var app = angular.module('myapp', []);

app.controller('Ctrl', function($scope) {
    $scope.myNnumber1 = 1;
    $scope.myNnumber2 = 1;
});

app.directive('isNumber', function () {
    return {
        require: 'ngModel',
        link: function (scope, element) {   
            scope.$watch(element.ngModel, function(newValue,oldValue) {
                newValue = String(newValue);
                newValue = newValue.replace('۰', '0').replace('۱', '1').replace('۲', '2').replace('۳', '3').replace('۴', '4').replace('۵', '5').replace('۶', '6').replace('۷', '7').replace('۸', '8').replace('۹', '9');
                var arr = String(newValue).split("");
                if (arr.length === 0) return;
                if (arr.length === 1 && (arr[0] == '-' || arr[0] === '.' )) return;
                if (arr.length === 2 && newValue === '-.') return;
                if (isNaN(newValue)) {
                    element.ngModel = oldValue;
                }
            });
        }
   };

Update: Please consider that I need to do some processes to convert non English numbers and so on. I created a new fiddle here based on the the Angular_10's answer. Now, every thing is fine except the cursor position while typing Persian numbers. When I type A Persian Number, it is replaced with English equivalent number, but the cursor suddenly jumps to the end.

like image 216
Happy Ahmad Avatar asked Dec 25 '17 21:12

Happy Ahmad


People also ask

How do I allow only numbers in Javascript?

By default, HTML 5 input field has attribute type=”number” that is used to get input in numeric format. Now forcing input field type=”text” to accept numeric values only by using Javascript or jQuery. You can also set type=”tel” attribute in the input field that will popup numeric keyboard on mobile devices.

What is Keyup event in angular?

(keyup): (keyup) is an Angular event binding to respond to any DOM event. It is a synchronous event that is triggered as the user is interacting with the text-based input controls. When a user presses and releases a key, the (keyup) event occurs.


1 Answers

OK ! Looking at your requirement I've took liberty and wrote more customised directive.

Here is the fiddle for the same

Problem

The example from which you referred and made changes to the given directive is causing the issue.

  1. Your $scope variable names are wrong in HTML/JS ($scope.myNnumber1 = 1; $scope.myNnumber2 = 1; in JS and in HTML it was ng-model="myNumber1")
  2. You are accessing element ng-model and trying to modify it through directive which is bad practice and also the root cause for directive to not to work.As you are not changing the ng-model value but in turn modifying HTML element value which angular will not recognise.
  3. More over using $watch in directive is not always preferable for performance sake.

Solution

app.directive('isNumber', function() {
    return {
        require: 'ngModel',
        restrict: 'A',
        link: function(scope, element, attr, ctrl) {
            function inputValue(val) {
                if (val) {
                    var numeric = val.replace(/[^- 0-9]/g, '');

                    if (numeric !== val) {
                        ctrl.$setViewValue(numeric );
                        ctrl.$render();
                    }
                    return numeric;
                }
                return undefined;
            }
            ctrl.$parsers.push(inputValue);
        }
    };

});

When controller communication is required from directive we can pass Controller as 4 param in the link function.From that Ctrl param we can modify/view things from controller scope.

Using some basic regex expression to find out what is the entered input and set it in the controller scope object view value.

ctrl.$setViewValue(numeric); //to set the value in the respective ngModdel
ctrl.$render(); //to display the changed value

More about $setViewValue

like image 80
ngCoder Avatar answered Oct 18 '22 18:10

ngCoder