数据绑定数字输入的最小/最大属性时不会触发验证

Kri*_*ris 11 angularjs

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

var myApp = angular.module('myApp', []);
function FirstCtrl($scope) {
    $scope.min = 10;
    $scope.max = 20;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

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

正如您所看到的,HTML/CSS(Bootstrap)中的验证仍然可以正常处理,因为两个字段在无效时变为红色,但是,当第二个字段无效时,不会禁用提交按钮(由Angular处理).另外,还有一些中没有的最小值和最大值的属性myForm.two.$error,因为在myForm.one.$error.

谁能看到我哪里出错了?

Gui*_*e86 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']);
Run Code Online (Sandbox Code Playgroud)

  • 几乎完美,但`var max = scope.$ eval(attr.ngMax)|| 无穷大;`将值0评估为无穷大. (3认同)
  • 几乎完美:)但在我的情况下,max或min值可能会根据其他值而改变,所以我不得不使用watch的函数形式:`scope.$ watch(function(){return {ngMax:attr. ngMax}},function(){ctrl.$ setViewValue(ctrl.$ viewValue);},true);` (3认同)

Mar*_*cok 9

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

if (attr.min) {
  var min = parseFloat(attr.min);
Run Code Online (Sandbox Code Playgroud)

$interpolate不叫,只是parseFloat,所以你需要指定一个字符串,它看起来像一个数minmax.

  • 那么这是一个错误还是什么?应该打开一个问题吗? (2认同)
  • 是的,这是一个缺失的功能 (2认同)