development

숫자 (숫자 및 소수점) 만 입력하도록 허용하는 방법은 무엇입니까?

big-blog 2020. 12. 13. 10:10
반응형

숫자 (숫자 및 소수점) 만 입력하도록 허용하는 방법은 무엇입니까?


저는 angularjs를 처음 사용합니다. 텍스트 상자에 입력 된 유효한 숫자 만 허용하는 방법이 궁금합니다. 예를 들어 사용자는 "1.25"를 입력 할 수 있지만 "1.a"또는 "1 .."은 입력 할 수 없습니다. 사용자가 유효하지 않은 숫자로 만드는 다음 문자를 입력하려고하면 입력 할 수 없습니다.

미리 감사드립니다.


이 지시문을 사용하여 유효하지 않은 문자가 입력 필드에 입력되지 않도록 할 수 있습니다. ( 업데이트 : 이것은 재사용에 이상적이지 않은 모델에 대한 명시적인 지식을 가진 지침에 의존합니다. 재사용 가능한 예는 아래를 참조하십시오.)

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. 음수 십진수 값

어떻게 작동하는지 볼 수 있도록 여기 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;
                }
            });
        }
    };
});

숫자 사용자 입력을 필터링하는 훌륭한 방법을 보여주기 위해 작동하는 CodePen 예제작성했습니다 . 지시문은 현재 양의 정수만 허용하지만 원하는 숫자 형식을 지원하도록 정규식을 쉽게 업데이트 할 수 있습니다.

내 지시문은 사용하기 쉽습니다.

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

이 지침은 매우 이해하기 쉽습니다.

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, '');
        if (val !== clean) {
          ngModelCtrl.$setViewValue(clean);
          ngModelCtrl.$render();
        }
        return clean;
      });

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

지침에서 모델 참조유지하는 것이 중요하다는 점 을 강조하고 싶습니다 .

도움이 되었기를 바랍니다.

ngModelController 를 소개 해주신 Sean Christe 와 Chris Grimes에게 감사드립니다.


우선 Adam thomas 덕분에 저는 소수 값을 받아들이 기 위해 약간의 수정으로 동일한 Adam의 논리를 사용했습니다.

참고 : 소수 2 자리 만 허용됩니다.

다음은 내 작업 예입니다.

HTML

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

자바 스크립트

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

단계 태그를 사용하여 변경 가능한 최소 값을 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/


DEMO - - 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>

참고 : 각도 js와 함께 jQuery를 포함하는 것을 잊지 마십시오


ng-pattern을 쉽게 사용할 수 있습니다.

ng-pattern="/^[1-9][0-9]{0,2}(?:,?[0-9]{3}){0,3}(?:\.[0-9]{1,2})?$/"

내가 원하는 것을 할 수 있다고 믿는 입력 번호 지시문이 있습니다.

<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


HTML

 <input type="text" name="number" only-digits>

// 123을 입력하십시오.

  .directive('onlyDigits', 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 !== val) {
              ctrl.$setViewValue(digits);
              ctrl.$render();
            }
            return parseInt(digits,10);
          }
          return undefined;
        }            
        ctrl.$parsers.push(inputValue);
      }
    };

// 입력 : 123 또는 123.45

 .directive('onlyDigits', 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 !== val) {
              ctrl.$setViewValue(digits);
              ctrl.$render();
            }
            return parseFloat(digits);
          }
          return undefined;
        }            
        ctrl.$parsers.push(inputValue);
      }
    };

범위 minmax속성이 다음과 같이 제한 될 수있는 지시문을 원했습니다 .

<input type="text" integer min="1" max="10" />

그래서 다음과 같이 썼습니다.

.directive('integer', function() {
    return {
        restrict: 'A',
        require: '?ngModel',
        link: function(scope, elem, attr, ngModel) {
            if (!ngModel)
                return;

            function isValid(val) {
                if (val === "")
                    return true;

                var asInt = parseInt(val, 10);
                if (asInt === NaN || asInt.toString() !== val) {
                    return false;
                }

                var min = parseInt(attr.min);
                if (min !== NaN && asInt < min) {
                    return false;
                }

                var max = parseInt(attr.max);
                if (max !== NaN && max < asInt) {
                    return false;
                }

                return true;
            }

            var prev = scope.$eval(attr.ngModel);
            ngModel.$parsers.push(function (val) {
                // short-circuit infinite loop
                if (val === prev)
                    return val;

                if (!isValid(val)) {
                    ngModel.$setViewValue(prev);
                    ngModel.$render();
                    return prev;
                }

                prev = val;
                return val;
            });
        }
    };
});

여기 내 정말 빠르고 더러운 것이 있습니다.

<!-- 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|\.)+$/? 항상 그렇듯이 완료되면 서버 측의 유효성을 검사하십시오.


이것은 나에게 가장 쉬운 것 같습니다 : http://jsfiddle.net/thomporter/DwKZh/

(코드는 내 것이 아닙니다, 실수로 우연히 발견했습니다)

    angular.module('myApp', []).directive('numbersOnly', function(){
       return {
         require: 'ngModel',
         link: function(scope, element, attrs, modelCtrl) {
           modelCtrl.$parsers.push(function (inputValue) {
               // this next if is necessary for when using ng-required on your input. 
               // In such cases, when a letter is typed first, this parser will be called
               // again, and the 2nd time, the value will be undefined
               if (inputValue == undefined) return '' 
               var transformedInput = inputValue.replace(/[^0-9]/g, ''); 
               if (transformedInput!=inputValue) {
                  modelCtrl.$setViewValue(transformedInput);
                  modelCtrl.$render();
               }         

               return transformedInput;         
           });
         }
       };
    });

위의 Alan의 대답을 수정하여 숫자를 지정된 최소 / 최대로 제한했습니다. 범위 밖의 숫자를 입력하면 1500ms 후에 최소 또는 최대 값이 설정됩니다. 필드를 완전히 지우면 아무것도 설정되지 않습니다.

HTML :

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

자바 스크립트 :

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

비슷한 문제가 있었고 input[type="number"]십진수 정밀도로 작업하기 위해 각도 문서 예제를 업데이트 했으며이 접근 방식을 사용하여 해결하고 있습니다.

추신 : 브라우저가 입력 [type = "number"]에서 'e'와 'E'문자를 지원한다는 점을 간단히 상기시켜줍니다 keypress. 이벤트가 필요 하기 때문입니다 .

angular.module('numfmt-error-module', [])
.directive('numbersOnly', function() {
  return {
    require: 'ngModel',
    scope: {
      precision: '@'
    },
    link: function(scope, element, attrs, modelCtrl) {
      var currencyDigitPrecision = scope.precision;

      var currencyDigitLengthIsInvalid = function(inputValue) {
        return countDecimalLength(inputValue) > currencyDigitPrecision;
      };

      var parseNumber = function(inputValue) {
        if (!inputValue) return null;
        inputValue.toString().match(/-?(\d+|\d+.\d+|.\d+)([eE][-+]?\d+)?/g).join('');
        var precisionNumber = Math.round(inputValue.toString() * 100) % 100;

        if (!!currencyDigitPrecision && currencyDigitLengthIsInvalid(inputValue)) {
          inputValue = inputValue.toFixed(currencyDigitPrecision);
          modelCtrl.$viewValue = inputValue;
        }
        return inputValue;
      };

      var countDecimalLength = function (number) { 
         var str = '' + number;
         var index = str.indexOf('.');
         if (index >= 0) {
           return str.length - index - 1;
         } else {
           return 0;
         }
      };

      element.on('keypress', function(evt) {
        var charCode, isACommaEventKeycode, isADotEventKeycode, isANumberEventKeycode;
        charCode = String.fromCharCode(evt.which || event.keyCode);
        isANumberEventKeycode = '0123456789'.indexOf(charCode) !== -1;
        isACommaEventKeycode = charCode === ',';
        isADotEventKeycode = charCode === '.';

        var forceRenderComponent = false;

        if (modelCtrl.$viewValue != null && !!currencyDigitPrecision) {
          forceRenderComponent = currencyDigitLengthIsInvalid(modelCtrl.$viewValue);
        }

        var isAnAcceptedCase = isANumberEventKeycode || isACommaEventKeycode || isADotEventKeycode;

        if (!isAnAcceptedCase) {
          evt.preventDefault();
        }

        if (forceRenderComponent) {
          modelCtrl.$render(modelCtrl.$viewValue);
        }

        return isAnAcceptedCase;
      });

      modelCtrl.$render = function(inputValue) {
        return element.val(parseNumber(inputValue));
      };

      modelCtrl.$parsers.push(function(inputValue) {

        if (!inputValue) {
          return inputValue;
        }

        var transformedInput;
        modelCtrl.$setValidity('number', true);
        transformedInput = parseNumber(inputValue);

        if (transformedInput !== inputValue) {

          modelCtrl.$viewValue = transformedInput;
          modelCtrl.$commitViewValue();
          modelCtrl.$render(transformedInput);
        }
        return transformedInput;
      });
    }
  };
});

그리고 HTML에서이 접근 방식을 사용할 수 있습니다.

<input 
  type="number" 
  numbers-only 
  precision="2" 
  ng-model="model.value" 
  step="0.10" />

다음은이 스 니펫이있는 플 런커입니다.


Gordy의 답변에서 확장 :

잘 했어 btw. 그러나 그것은 또한 전면에 +를 허용했습니다. 이것은 그것을 제거합니다.

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

여기에 두 번 입력되는 소수점을 차단하는 미분이 있습니다.

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

Adam Thomas 답변을 확장하면 사용자 정의 regexp로 입력 인수를 추가 하여이 지시문을 더 일반적으로 쉽게 만들 수 있습니다.

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에서 라이브


특정 데이터 유형 만 허용하는 데 도움이되는 내 구성 요소를 확인하십시오. 현재 정수, 십진수, 문자열 및 시간 (HH : MM)을 지원합니다.

  • string -문자열은 선택 가능한 최대 길이로 허용됩니다.
  • integer - Integer only allowed with optional max value
  • decimal - Decimal only allowed with optional decimal points and max value (by default 2 decimal points)
  • time - 24 hr Time format(HH:MM) only allowed

https://github.com/ksnimmy/txDataType

Hope that helps.


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

참고URL : https://stackoverflow.com/questions/19036443/how-to-allow-only-a-number-digits-and-decimal-point-to-be-typed-in-an-input

반응형