11

我有许多数字输入字段,它们的最小值和最大值属性值取决于我的 AngularJS 应用程序中其他地方的逻辑,但是当在这些属性中使用数据绑定时,Angular 不再验证它们,但是,HTML 5 验证似乎仍然选择它们向上。

var myApp = angular.module('myApp', []);
function FirstCtrl($scope) {
    $scope.min = 10;
    $scope.max = 20;
}
<div ng-app="myApp">
    <div ng-controller="FirstCtrl">
        <form name="myForm">
            <input type="number" name="one" required="required"
                   min="10" max="20" ng-model="one" />
            <input type="number" name="two" required="required"
                   min="{{ min }}" max="{{ max }}" ng-model="two" />
            <button ng-disabled="!myForm.$valid">Submit</button>
        </form>
    </div>
</div>

现场版:http: //jsfiddle.net/kriswillis/bPUVH/2/

如您所见,验证仍然在 HTML/CSS(引导程序)中处理得很好,因为两个字段在无效时都会变成红色,但是,当第二个字段无效时,提交按钮(由 Angular 处理)不会被禁用。myForm.two.$error此外,在中没有 min 和 max 属性myForm.one.$error

谁能看到我哪里出错了?

4

5 回答 5

22

我编写了指令来填补空白,ng-min 和 ng-max:

http://jsfiddle.net/g/s5gKC/

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

function isEmpty(value) {
  return angular.isUndefined(value) || value === '' || value === null || value !== value;
}

app.directive('ngMin', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elem, attr, ctrl) {
            scope.$watch(attr.ngMin, function(){
                ctrl.$setViewValue(ctrl.$viewValue);
            });
            var minValidator = function(value) {
              var min = scope.$eval(attr.ngMin) || 0;
              if (!isEmpty(value) && value < min) {
                ctrl.$setValidity('ngMin', false);
                return undefined;
              } else {
                ctrl.$setValidity('ngMin', true);
                return value;
              }
            };

            ctrl.$parsers.push(minValidator);
            ctrl.$formatters.push(minValidator);
        }
    };
});

app.directive('ngMax', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elem, attr, ctrl) {
            scope.$watch(attr.ngMax, function(){
                ctrl.$setViewValue(ctrl.$viewValue);
            });
            var maxValidator = function(value) {
              var max = scope.$eval(attr.ngMax) || Infinity;
              if (!isEmpty(value) && value > max) {
                ctrl.$setValidity('ngMax', false);
                return undefined;
              } else {
                ctrl.$setValidity('ngMax', true);
                return value;
              }
            };

            ctrl.$parsers.push(maxValidator);
            ctrl.$formatters.push(maxValidator);
        }
    };
});

angular.bootstrap(document.body, ['app']);
于 2013-04-26T17:53:45.330 回答
9

显然我们不能对minandmax字段使用 {{}}(即插值)。我查看了源代码,发现以下内容:

if (attr.min) {
  var min = parseFloat(attr.min);

$interpolate不调用,只是parseFloat,因此您需要为minand指定一个看起来像数字的字符串max

于 2013-03-27T14:51:09.993 回答
2

Angular 现在似乎支持ng-min并且ng-max开箱即用,而无需编写自己的指令。请参阅使用 Angular 1.4.2 的这个小提琴。

于 2015-08-03T22:06:13.477 回答
0

我还为它写了一个自定义指令:

工作演示:http ://plnkr.co/edit/BJ98ZR?p=preview

.directive('validateRange', ['$parse', function($parse) {

    function link($scope, $element, $attrs, ngModel) {
        var attrRange, range = [];

        function validate(value) {
            var validMin = true, validMax = true;
            if (typeof range[0] === 'number') {
                ngModel.$setValidity('min', value >= range[0]);
                validMin = value >= range[0];
            }
            if (typeof range[1] === 'number') {
                ngModel.$setValidity('max', value <= range[1]);
                validMax = value <= range[1];
            }
            return validMin && validMax ? value : undefined;
        }

        attrRange = $attrs.validateRange.split(/,/);

        range[0] = $parse(attrRange[0] || '')($scope);
        range[1] = $parse(attrRange[1] || '')($scope);

        $scope.$watchCollection('[' + $attrs.validateRange + ']', function(values) {
            range = values;
            validate(ngModel.$viewValue);
        });

        ngModel.$parsers.unshift(validate);
        ngModel.$formatters.unshift(validate);
    }

    return {
        link: link,
        require: 'ngModel'
    };

}]);

示例使用:

<form name="myform" ng-init="minvalue=0;value=1;maxvalue=2">
    Min Value:
    <input type="number" name="minvalue" required
           data-validate-range="0,value"
           ng-model="minvalue">

    Value:
    <input type="number" name="value" required
           data-validate-range="minvalue,maxvalue"
           ng-model="value">

    Max Value:
    <input type="number" name="maxvalue" required
           data-validate-range="value,false"
           ng-model="maxvalue">

    <pre>
        myform.minvalue.$error {{ myform.minvalue.$error }}
        myform.value.$error    {{ myform.value.$error }}
        myform.maxvalue.$error {{ myform.maxvalue.$error }}
    </pre>
</form>
于 2014-05-08T14:14:21.283 回答
-1

我也面临同样的问题。通过使用此指令获得成功:

angular.module('tech').directive('maximum', ['$parse',
  function($parse) {
    return {
      restrict: 'A',
      require: '?ngModel',

      link: function(scope, element, attrs, ctrl) {

        if (!ctrl) return;
        attrs.maximum = true;


        var checkMax = function(n) {
          if (!n) return;

          var actualValue = ctrl.$viewValue;
          var maxValue = attrs.maximum;
          if (parseInt(actualValue) > parseInt(maxValue)) {
            ctrl.$setValidity('maximum', false);
          } else {
            ctrl.$setValidity('maximum', true);
          }
        };
        scope.$watch(attrs.ngModel, checkMax);
        //attrs.$observe('ngModel', remind);
        attrs.$observe('maximum', checkMax);

      }
    }
  }
]);

我从这个网站得到了这个解决方案。对于整个代码,你可以去这个网站

于 2015-02-01T10:43:10.500 回答