Валидация не срабатывает, когда данные привязывают числовые значения min/max
У меня есть многочисленные поля ввода чисел, которые имеют значения атрибутов min и max, которые зависят от логики в другом месте моего приложения 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
.
Кто-нибудь может увидеть, где я ошибаюсь?
Ответы
Ответ 1
По-видимому, мы не можем использовать {{}} s (т.е. интерполяцию) для полей min
и max
. Я посмотрел исходный код и нашел следующее:
if (attr.min) {
var min = parseFloat(attr.min);
$interpolate
не вызывается, просто parseFloat
, поэтому вам нужно указать строку, которая выглядит как число для min
и max
.
Ответ 2
Я написал директивы для заполнения пробела, 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']);
Ответ 3
Angular теперь поддерживает ng-min
и ng-max
из коробки без необходимости писать собственные директивы. См. этот скрипт, который использует Angular 1.4.2.
Ответ 4
Я также написал для него настраиваемую директиву:
.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>
Ответ 5
У меня одна и та же проблема. получил успех, используя эту директиву:
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);
}
}
}
]);
Я получил это решение из этого веб-сайта. для всего кода вы можете перейти этот веб-сайт