我有许多数字输入字段,其最小和最大属性值取决于我的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(Bootstrap)中的验证仍处于正常状态,因为两个字段在无效时变为红色,但是,当第二个字段无效时,不会禁用提交按钮(由Angular处理)。此外,myForm.two.$error
中没有myForm.one.$error
中的最小和最大属性。
谁能看到我出错的地方?
答案 0 :(得分:22)
我写了指令来填补空白,ng-min和ng-max:
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']);
答案 1 :(得分:9)
显然,我们无法对min
和max
字段使用{{}} s(即插值)。我看了source code,发现了以下内容:
if (attr.min) {
var min = parseFloat(attr.min);
$interpolate
未被调用,只是parseFloat
,因此您需要指定一个类似于min
和max
的数字的字符串。
答案 2 :(得分:2)
Angular似乎现在支持ng-min
和ng-max
开箱即用,而无需编写自己的指令。请参阅使用Angular 1.4.2的this Fiddle。
答案 3 :(得分:0)
我还为它写了一个自定义指令:
.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>
答案 4 :(得分:-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);
}
}
}
]);