Angularjs 如果以后更改值,则最小/最大验证不起作用

Angularjs 如果以后更改值,则最小/最大验证不起作用,angularjs,Angularjs,我有一个要求,其中一个字段的最小值取决于另一个字段中给定的输入 <input type="number" name="minval" class="form-control" ng-model="user.minval" ng-required="true"> 此输入用于验证另一个字段 <input type="number" name="inputval" class="form-control" ng-model="user.inputval"

我有一个要求,其中一个字段的最小值取决于另一个字段中给定的输入

<input type="number" name="minval" class="form-control" ng-model="user.minval" 
      ng-required="true">

此输入用于验证另一个字段

<input type="number" name="inputval" class="form-control" ng-model="user.inputval" 
     ng-required="true" min="{{user.minval}}">

但这并没有像预期的那样起作用。。如果我稍后更改“minval”,则输入不会重新验证

我已经尝试过从JS中设置min的初始值,正如某些解决方案中建议的那样,但这也没有帮助


使用ng min/ng max指令

app.directive('ngMin', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, elem, attr, ctrl) {
            scope.$watch(attr.ngMin, function(){
                if (ctrl.$isDirty) ctrl.$setViewValue(ctrl.$viewValue);
            });

            var isEmpty = function (value) {
               return angular.isUndefined(value) || value === "" || value === null;
            }

            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(){
                if (ctrl.$isDirty) 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);
        }
    };
});
app.directive('ngMin',function(){
返回{
限制:“A”,
要求:'ngModel',
链接:函数(作用域、元素、属性、ctrl){
作用域:$watch(attr.ngMin,函数(){
如果(ctrl.$isDirty)ctrl.$setViewValue(ctrl.$viewValue);
});
var isEmpty=函数(值){
返回角度.isUndefined(value)| | value==“”| | value==null;
}
var minValidator=函数(值){
var min=范围$eval(attr.ngMin)| 0;
如果(!isEmpty(value)&&valuemax){
ctrl.$setValidity('ngMax',false);
返回未定义;
}否则{
ctrl.$setValidity('ngMax',true);
返回值;
}
};
ctrl.$parsers.push(maxValidator);
ctrl.$formatters.push(maxValidator);
}
};
});

我已经开发了两个指令,它们实际上限制用户设置无效值,而不是在提供无效值时简单地抛出错误

这些指令也不需要ngModel(尽管我怀疑您是否会使用它们),真正酷的是如果提供了这两个设置,它会将值包装到最小/最大值

我试图尽可能地简化指令,以使读者更容易阅读

这里是整个事情的一个缩影:

以下是指令:

app.directive('ngMin', function($parse){
    return {
        restrict: 'A',
        link: function(scope, element, attrs){
            function validate(){
                if(element
                && element[0]
                && element[0].localName === 'input'
                && isNumber(attrs.ngMin)
                && isNumber(element[0].value)
                && parseFloat(element[0].value) < parseFloat(attrs.ngMin)){
                    if(isNumber(attrs.ngMax)){
                        element[0].value = parseFloat(attrs.ngMax);
                        if(attrs.hasOwnProperty("ngModel"))
                            $parse(attrs.ngModel).assign(scope, parseFloat(attrs.ngMax));
                    }
                    else {
                        element[0].value = parseFloat(attrs.ngMin);
                        if(attrs.hasOwnProperty("ngModel"))
                            $parse(attrs.ngModel).assign(scope, parseFloat(attrs.ngMin));
                    }
                }
            }
            scope.$watch(function(){
                return attrs.ngMin + "-" + element[0].value;
            }, function(newVal, oldVal){
                if(newVal != oldVal)
                    validate();
            });
            validate();
        }
    };
});
app.directive('ngMax', function($parse){
    return {
        restrict: 'A',
        link: function(scope, element, attrs){
            function validate(){
                if(element
                && element[0]
                && element[0].localName === 'input'
                && isNumber(attrs.ngMax)
                && isNumber(element[0].value)
                && parseFloat(element[0].value) > parseFloat(attrs.ngMax)){
                    if(isNumber(attrs.ngMin)){
                        element[0].value = parseFloat(attrs.ngMin);
                        if(attrs.hasOwnProperty("ngModel"))
                            $parse(attrs.ngModel).assign(scope, parseFloat(attrs.ngMin));
                    }
                    else {
                        element[0].value = parseFloat(attrs.ngMax);
                        if(attrs.hasOwnProperty("ngModel"))
                            $parse(attrs.ngModel).assign(scope, parseFloat(attrs.ngMax));
                    }
                }
            }
            scope.$watch(function(){
                return attrs.ngMax + "-" + element[0].value;
            }, function(newVal, oldVal){
                if(newVal != oldVal)
                    validate();
            });
            validate();
        }
    };
});
要调用这些指令,只需在输入框中设置它们,其中
type=“number”


这就应该做到了

当您同时提供
ngMin
ngMax
时,这些指令将环绕该值,以便当您的值小于
ngMin
时,它将设置为
ngMax
,反之亦然

如果只提供
ngMin
ngMax
,则输入值将仅限于这些值


我更喜欢这种防止错误值的方法,而不是提醒用户他们输入了错误值。

如果第一次输入的原始最小值低于第二次输入值,您希望发生什么情况?通过大量的谷歌搜索,我发现了一个非常有用的SO帖子:非常感谢@Forget Fulfellow,我想我不需要回答你的第一个评论。。这个链接是我面临的问题的答案。谢谢你的工作。另外,如果将required属性与这些指令结合使用,字段会立即被标记为无效,这对用户来说不是很友好。您可以通过在watch
if(ctrl.$isDirty).
中检查字段是否脏来修复此问题,然后只执行setViewValue。@akiro实际上我在代码中已经这样做了,忘了更新答案。无论如何,谢谢你的输入。真的吗?你想用手表吗?。。。嘿,isEmpty()没有定义这个解决方案首先出现在这里:请注意,现在Angular支持ng min和ng max,而无需编写自己的指令。
function isNumber(n){
    return !isNaN(parseFloat(n)) && isFinite(n);
}
<input ng-model="myModel" ng-min="0" ng-max="1024" />