Eu tenho vários campos de input numéricos que têm valores de atributos min e max que dependem da lógica em outro lugar no meu aplicativo AngularJS, mas quando usando ligações de dados dentro desses atributos eles não são mais validados pelo Angular, no entanto, a validação HTML 5 ainda aparece para selecioná-los acima.
var myApp = angular.module('myApp', []); function FirstCtrl($scope) { $scope.min = 10; $scope.max = 20; }
Versão ao vivo: http://jsfiddle.net/kriswillis/bPUVH/2/
Como você pode ver, a validação ainda é tratada bem no HTML / CSS (Bootstrap), pois ambos os campos ficam vermelhos quando inválidos, no entanto, o botão de envio (tratado pelo Angular) não é desabilitado quando o segundo campo é inválido. Além disso, não há propriedades min e max no myForm.two.$error
Como existem no myForm.one.$error
.
Alguém pode ver onde estou indo errado?
Aparentemente, não podemos usar {{}} s (ou seja, interpolação) para os campos min
e max
. Eu olhei para o código-fonte e achei o seguinte:
if (attr.min) { var min = parseFloat(attr.min);
$interpolate
não é chamado, apenas parseFloat
, então você precisa especificar uma string parecida com um número para min
e max
.
Eu escrevi diretivas para preencher a lacuna, ng-min e 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']);
Angular parece agora suportar ng-min
e ng-max
para uso sem a necessidade de escrever suas próprias diretivas. Veja este violino que está usando Angular 1.4.2.
Eu também escrevi uma diretiva personalizada para isso:
.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' }; }]);
Exemplo de uso:
Eu enfrento o mesmo problema. obteve sucesso usando esta diretiva:
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); } } } ]);
Eu tenho essa solução deste site. para todo o código você pode ir para este site