58

I am new to angularjs. I am wondering what is the way to allow only a valid number typed into a textbox. For example, user can type in "1.25", but cannot type in "1.a" or "1..". When user try to type in the next character which will make it an invalid number, he cannot type it in.

Thanks in advance.

4

18 に答える 18

52

このディレクティブを試して、無効な文字が入力フィールドに入力されるのを防ぐことができます。(更新:これは、モデルの明示的な知識を持つディレクティブに依存しており、再利用には理想的ではありません。再利用可能な例については、以下を参照してください)

app.directive('isNumber', function () {
    return {
        require: 'ngModel',
        link: function (scope) {    
            scope.$watch('wks.number', function(newValue,oldValue) {
                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)) {
                    scope.wks.number = oldValue;
                }
            });
        }
    };
});

また、次のシナリオも説明します。

  1. 空でない有効な文字列から空の文字列への移行
  2. 負の値
  3. 負の 10 進数値

ここでjsFiddleを作成したので、それがどのように機能するかを確認できます。

アップデート

ディレクティブ内にモデル参照を直接含めないことに関する Adam Thomas のフィードバック (これも最善の方法だと思います)に従って、これに依存しないメソッドを提供するようにjsFiddleを更新しました。

このディレクティブは、ローカル スコープの親スコープへの双方向バインディングを利用します。ディレクティブ内の変数に加えられた変更は親スコープに反映され、その逆も同様です。

HTML:

<form ng-app="myapp" name="myform" novalidate> 
    <div ng-controller="Ctrl">
        <number-only-input input-value="wks.number" input-name="wks.name"/>
    </div>
</form>

角度コード:

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

app.controller('Ctrl', function($scope) {
    $scope.wks =  {number: 1, name: 'testing'};
});
app.directive('numberOnlyInput', function () {
    return {
        restrict: 'EA',
        template: '<input name="{{inputName}}" ng-model="inputValue" />',
        scope: {
            inputValue: '=',
            inputName: '='
        },
        link: function (scope) {
            scope.$watch('inputValue', function(newValue,oldValue) {
                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)) {
                    scope.inputValue = oldValue;
                }
            });
        }
    };
});
于 2013-09-26T19:30:23.913 に答える
45

まず、Adam thomas に感謝します。これには同じ Adam のロジックを使用し、10 進値を受け入れるように少し変更を加えました。

注: これにより、小数点以下 2 桁のみの数字が許可されます。

ここに私の作業例があります

HTML

<input type="text" ng-model="salary" valid-number />

Javascript

    var app = angular.module('myApp', []);

    app.controller('MainCtrl', function($scope) {
    });

    app.directive('validNumber', function() {
      return {
        require: '?ngModel',
        link: function(scope, element, attrs, ngModelCtrl) {
          if(!ngModelCtrl) {
            return; 
          }

          ngModelCtrl.$parsers.push(function(val) {
            if (angular.isUndefined(val)) {
                var val = '';
            }
            var clean = val.replace(/[^0-9\.]/g, '');
            var decimalCheck = clean.split('.');

            if(!angular.isUndefined(decimalCheck[1])) {
                decimalCheck[1] = decimalCheck[1].slice(0,2);
                clean =decimalCheck[0] + '.' + decimalCheck[1];
            }

            if (val !== clean) {
              ngModelCtrl.$setViewValue(clean);
              ngModelCtrl.$render();
            }
            return clean;
          });

          element.bind('keypress', function(event) {
            if(event.keyCode === 32) {
              event.preventDefault();
            }
          });
        }
      };
    });
于 2014-11-27T05:43:26.837 に答える
10

step タグを使用して、変更可能な最小値を 10 進数に設定します。

例 step="0.01"

<input type="number" step="0.01" min="0" class="form-control" 
name="form_name" id="your_id" placeholder="Please Input a decimal number" required>

ここにいくつかのドキュメントがあります:

http://blog.isotoma.com/2012/03/html5-input-typenumber-and-decimalsfloats-in-chrome/

于 2014-05-19T21:46:08.930 に答える
7

デモ- - jsFiddle

指令

   .directive('onlyNum', function() {
      return function(scope, element, attrs) {

         var keyCode = [8,9,37,39,48,49,50,51,52,53,54,55,56,57,96,97,98,99,100,101,102,103,104,105,110];
          element.bind("keydown", function(event) {
            console.log($.inArray(event.which,keyCode));
            if($.inArray(event.which,keyCode) == -1) {
                scope.$apply(function(){
                    scope.$eval(attrs.onlyNum);
                    event.preventDefault();
                });
                event.preventDefault();
            }

        });
     };
  });

HTML

 <input type="number" only-num>

注:angular jsでjQueryを含めることを忘れないでください

于 2013-11-14T08:35:21.930 に答える
5

あなたが望むことだけを行うことができると私が信じている入力番号ディレクティブがあります。

<input type="number"
   ng-model="{string}"
   [name="{string}"]
   [min="{string}"]
   [max="{string}"]
   [required]
   [ng-required="{string}"]
   [ng-minlength="{number}"]
   [ng-maxlength="{number}"]
   [ng-pattern="{string}"]
   [ng-change="{string}"]>

公式ドキュメントはこちら: http://docs.angularjs.org/api/ng.directive:input.number

于 2013-09-26T19:58:35.407 に答える
1

これが私の本当に素早い汚れたものです:

<!-- HTML file -->
<html ng-app="num">
  <head></head>
  <body ng-controller="numCtrl">
    <form class="digits" name="digits" ng-submit="getGrades()" novalidate >
      <input type="text" placeholder="digits here plz" name="nums" ng-model="nums" required ng-pattern="/^(\d)+$/" />
      <p class="alert" ng-show="digits.nums.$error.pattern">Numbers only, please.</p> 
      <br>
      <input type="text" placeholder="txt here plz" name="alpha" ng-model="alpha" required ng-pattern="/^(\D)+$/" />
      <p class="alert" ng-show="digits.alpha.$error.pattern">Text only, please.</p>
      <br>
      <input class="btn" type="submit" value="Do it!" ng-disabled="!digits.$valid" />
    </form>
  </body>
</html>

// Javascript file
var app = angular.module('num', ['ngResource']);
app.controller('numCtrl', function($scope, $http){
  $scope.digits = {};
});

これには、検証目的でフィールドへの永続的なバインディングのために angular-resource ライブラリを含める必要があります。

作業例はこちら

1.2.0-rc.3+ でチャンピオンのように動作します。正規表現を変更すると、すべて設定されます。おそらく何かのような/^(\d|\.)+$/?いつものように、完了したらサーバー側を検証します。

于 2013-11-06T09:04:28.327 に答える
1

上記の Alan の回答を修正して、数値を指定された最小/最大に制限しました。範囲外の数値を入力すると、1500ms 後に最小値または最大値が設定されます。フィールドを完全にクリアすると、何も設定されません。

HTML:

<input type="text" ng-model="employee.age" min="18" max="99" valid-number />

Javascript:

var app = angular.module('myApp', []);

app.controller('MainCtrl', function($scope) {});

app.directive('validNumber', function($timeout) {
    return {
        require: '?ngModel',
        link: function(scope, element, attrs, ngModelCtrl) {
            if (!ngModelCtrl) {
                return;
            }

            var min = +attrs.min;
            var max = +attrs.max;
            var lastValue = null;
            var lastTimeout = null;
            var delay = 1500;

            ngModelCtrl.$parsers.push(function(val) {
                if (angular.isUndefined(val)) {
                    val = '';
                }            

                if (lastTimeout) {
                    $timeout.cancel(lastTimeout);
                }

                if (!lastValue) {
                    lastValue = ngModelCtrl.$modelValue;
                }

                if (val.length) {
                    var value = +val;
                    var cleaned = val.replace( /[^0-9]+/g, ''); 

                    // This has no non-numeric characters
                    if (val.length === cleaned.length) {
                        var clean = +cleaned;

                        if (clean < min) {
                            clean = min;
                        } else if (clean > max) {
                            clean = max;
                        }

                        if (value !== clean || value !== lastValue) {
                            lastTimeout = $timeout(function () {
                                lastValue = clean;
                                ngModelCtrl.$setViewValue(clean);
                                ngModelCtrl.$render();
                            }, delay);
                        }
                    // This has non-numeric characters, filter them out
                    } else {
                        ngModelCtrl.$setViewValue(lastValue);
                        ngModelCtrl.$render();
                    }
                }

                return lastValue;
            });

            element.bind('keypress', function(event) {
                if (event.keyCode === 32) {
                    event.preventDefault();
                }
            });

            element.on('$destroy', function () {
                element.unbind('keypress');
            });
        }
    };
});
于 2014-11-26T02:05:02.363 に答える
0

Adam Thomas の回答を拡張すると、カスタム正規表現を使用して入力引数を追加することで、このディレクティブをより一般的なものにすることができます。

var app = angular.module('myApp', []);

app.controller('MainCtrl', function($scope) {
});

app.directive('validInput', function() {
  return {
    require: '?ngModel',
    scope: {
      "inputPattern": '@'
    },
    link: function(scope, element, attrs, ngModelCtrl) {

      var regexp = null;

      if (scope.inputPattern !== undefined) {
        regexp = new RegExp(scope.inputPattern, "g");
      }

      if(!ngModelCtrl) {
        return;
      }

      ngModelCtrl.$parsers.push(function(val) {
        if (regexp) {
          var clean = val.replace(regexp, '');
          if (val !== clean) {
            ngModelCtrl.$setViewValue(clean);
            ngModelCtrl.$render();
          }
          return clean;
        }
        else {
          return val;
        }

      });

      element.bind('keypress', function(event) {
        if(event.keyCode === 32) {
          event.preventDefault();
        }
      });
    }
}});

HTML

<input type="text" ng-model="employee.age" valid-input  
       input-pattern="[^0-9]+" placeholder="Enter an age" />
</label>

CodePenでライブ

于 2015-03-30T12:17:41.113 に答える
0

gordy の回答からの拡張:

ところで良い仕事。しかし、前に + を入れることもできました。これで削除されます。

    scope.$watch('inputValue', function (newValue, oldValue) {
        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)) {
            scope.inputValue = oldValue;
        }
        if (arr.length > 0) {
            if (arr[0] === "+") {
                scope.inputValue = oldValue;
            }
        }
    });
于 2014-05-29T01:00:54.567 に答える
0

特定のデータ型のみを許可するのに役立つ私のコンポーネントをチェックしてください。現在、整数、10 進数、文字列、時間 (HH:MM) をサポートしています。

  • string- 文字列はオプションの最大長で許可されます
  • integer- オプションの最大値でのみ許可される整数
  • decimal- 10 進数は、オプションの小数点と最大値でのみ許可されます (デフォルトでは小数点 2 桁)。
  • time- 24 時間形式 (HH:MM) のみ使用可能

https://github.com/ksnimmy/txDataType

それが役立つことを願っています。

于 2016-12-14T06:58:55.677 に答える
0

DECIMAL

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

                                if (digits.split('.').length > 2) {
                                    digits = digits.substring(0, digits.length - 1);
                                }

                                if (digits !== val) {
                                    ctrl.$setViewValue(digits);
                                    ctrl.$render();
                                }
                                return parseFloat(digits);
                            }
                            return "";
                        }
                        ctrl.$parsers.push(inputValue);
                    }
                };
            });

DIGITS

directive('entero', function() {
            return {
                require: 'ngModel',
                restrict: 'A',
                link: function(scope, element, attr, ctrl) {
                    function inputValue(val) {
                        if (val) {
                            var value = val + ''; //convert to string
                            var digits = value.replace(/[^0-9]/g, '');

                            if (digits !== value) {
                                ctrl.$setViewValue(digits);
                                ctrl.$render();
                            }
                            return parseInt(digits);
                        }
                        return "";
                    }
                    ctrl.$parsers.push(inputValue);
                }
            };
        });

angular directives for validate numbers

于 2017-01-06T16:47:23.017 に答える
0

これは、小数点を2回入力することもブロックする導関数です

HTML

    <input tabindex="1" type="text" placeholder="" name="salary" id="salary" data-ng-model="salary" numbers-only="numbers-only" required="required">

角度

    var app = angular.module("myApp", []);

    app.directive('numbersOnly', function() {
    return {
            require : 'ngModel', link : function(scope, element, attrs,  modelCtrl) {
        modelCtrl.$parsers.push(function(inputValue) {

            if (inputValue == undefined) {
                return ''; //If value is required
            }

            // Regular expression for everything but [.] and [1 - 10] (Replace all)
            var transformedInput = inputValue.replace(/[a-z!@#$%^&*()_+\-=\[\]{};':"\\|,<>\/?]/g, '');

            // Now to prevent duplicates of decimal point
            var arr = transformedInput.split('');

            count = 0; //decimal counter
            for ( var i = 0; i < arr.length; i++) {
                if (arr[i] == '.') {
                    count++; //  how many do we have? increment
                }
            }

            // if we have more than 1 decimal point, delete and leave only one at the end
            while (count > 1) {
                for ( var i = 0; i < arr.length; i++) {
                    if (arr[i] == '.') {
                        arr[i] = '';
                        count = 0;
                        break;
                    }
                }
            }

            // convert the array back to string by relacing the commas
            transformedInput = arr.toString().replace(/,/g, '');

            if (transformedInput != inputValue) {
                modelCtrl.$setViewValue(transformedInput);
                modelCtrl.$render();
            }

            return transformedInput;
        });
    }
};
});
于 2015-03-01T12:06:27.270 に答える