Angular 指令:只允许数字

Angular directive: Allow just numbers

这里是a sample angular directive to prevent typing non-numeric keys (Whosebug answer)。 我想写一些类似 this fiddle 的东西来在多个输入中使用 is-number 指令。请注意,由于我的输入中有各种不同的指令,我不能使用上述答案更新中建议的相同模板。

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;
                }
            });
        }
   };

更新: 请考虑我需要做一些处理来转换非英文数字等。我根据 Angular_10 的回答创建了 a new fiddle here。现在,除了输入波斯数字时的光标位置外,一切都很好。当我输入波斯语数字时,它被替换为等效的英文数字,​​但光标突然跳到末尾。

好的!查看您的要求,我自由地编写了更多自定义指令。

这是相同的

fiddle

问题

您引用并更改给定指令的示例导致了问题。

  1. 你的 $scope 变量名在 HTML/JS 中是错误的 ($scope.myNnumber1 = 1; $scope.myNnumber2 = 1;在 JS 和 HTML 中是 ng-model="myNumber1")
  2. 您正在访问 element ng-model 并试图通过指令修改它,这是不好的做法,也是指令不 work.As 的根本原因 您没有更改 ng-model 值但反过来修改 HTML 元素值,angular 将无法识别。
  3. 为了性能起见,在指令中使用 $watch 并不总是可取的。

解决方案

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);
        }
    };

});

当指令需要控制器通信时,我们可以在 link function.From 中将控制器作为 4 参数传递给 Ctrl 参数,我们可以 modify/view 控制器范围内的东西。

使用一些基本的正则表达式找出输入的内容并将其设置在控制器范围对象视图值中。

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

更多关于$setViewValue

我终于使用了下面的指令。该指令转换波斯数字,并且不允许在文本框中输入任何数字。特别感谢 Angular_10。由于他的帮助,我奖励了他 50 个赏金。

app.directive('fixPersianAndNoNumberInput', function ($filter) {
    return {
        require: 'ngModel',
        restrict: 'EA',
        link: function (scope, element, attr, controller) {
            function inputValue(val) {
                if (val) {
                    let numeric = parseInt(String(val).replace('۰', '0').replace('۱', '1').replace('۲', '2').replace('۳', '3').replace('۴', '4').replace('۵', '5').replace('۶', '6').replace('۷', '7').replace('۸', '8').replace('۹', '9').replace(' ', '000').replace(/[^- 0-9]/g, ''));
                    if (numeric !== val) {
                        controller.$setViewValue(numeric);
                        controller.$render();
                        let value;
                        let updateOn, debounce;
                        if (controller.$options) {
                            if (controller.$options.getOption) {
                                updateOn = controller.$options.getOption('updateOn');
                                debounce = controller.$options.getOption('debounce');
                            } else {
                                updateOn = controller.$options.updateOn;
                                debounce = controller.$options.debounce;
                            }
                        }
                        if (updateOn === 'blur' || debounce) {
                            value = controller.$viewValue;
                            for (let i = controller.$parsers.length - 1; i >= 0; i--) {
                                value = controller.$parsers[i](value);
                            }
                        } else {
                            value = controller.$$rawModelValue;
                        }
                        for (let j = controller.$formatters.length - 1; j >= 0; j--) {
                            value = controller.$formatters[j](value);
                        }
                        controller.$viewValue = value;
                        controller.$render();
                    }
                    return numeric;
                }
                return undefined;
            }

            controller.$parsers.push(inputValue);
            controller.$formatters.push((value) => {
                if ([undefined, null, ''].indexOf(value) === -1) {
                   return $filter('currency')(value, '', 0);
                }
                return value;
            });
        }
    };
});