fix(ngModel): revalidate the model when min/max expression values change for number inputs

As of this fix if the max or min value is changed via scope or by another ngModel
then it will trigger the model containing the min/max attributes to revalidate itself.

Closes #2404
This commit is contained in:
Matias Niemelä
2014-09-03 15:02:46 -04:00
parent 3952408cf1
commit 7b273a2c97
2 changed files with 54 additions and 14 deletions

View File

@@ -1129,15 +1129,35 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
});
if (attr.min) {
var minVal;
ctrl.$validators.min = function(value) {
return ctrl.$isEmpty(value) || isUndefined(attr.min) || value >= parseFloat(attr.min);
return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;
};
attr.$observe('min', function(val) {
if (isDefined(val) && !isNumber(val)) {
val = parseFloat(val, 10);
}
minVal = isNumber(val) && !isNaN(val) ? val : undefined;
// TODO(matsko): implement validateLater to reduce number of validations
ctrl.$validate();
});
}
if (attr.max) {
var maxVal;
ctrl.$validators.max = function(value) {
return ctrl.$isEmpty(value) || isUndefined(attr.max) || value <= parseFloat(attr.max);
return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;
};
attr.$observe('max', function(val) {
if (isDefined(val) && !isNumber(val)) {
val = parseFloat(val, 10);
}
maxVal = isNumber(val) && !isNaN(val) ? val : undefined;
// TODO(matsko): implement validateLater to reduce number of validations
ctrl.$validate();
});
}
}

View File

@@ -2894,18 +2894,28 @@ describe('input', function() {
expect(scope.form.alias.$error.min).toBeFalsy();
});
it('should validate even if min value changes on-the-fly', function(done) {
it('should validate even if min value changes on-the-fly', function() {
scope.min = 10;
compileInput('<input type="number" ng-model="value" name="alias" min="{{min}}" />');
changeInputValueTo('5');
changeInputValueTo('15');
expect(inputElm).toBeValid();
scope.min = 20;
scope.$digest();
expect(inputElm).toBeInvalid();
scope.min = 0;
scope.$digest(function () {
expect(inputElm).toBeValid();
done();
});
scope.min = null;
scope.$digest();
expect(inputElm).toBeValid();
scope.min = '20';
scope.$digest();
expect(inputElm).toBeInvalid();
scope.min = 'abc';
scope.$digest();
expect(inputElm).toBeValid();
});
});
@@ -2926,7 +2936,7 @@ describe('input', function() {
expect(scope.form.alias.$error.max).toBeFalsy();
});
it('should validate even if max value changes on-the-fly', function(done) {
it('should validate even if max value changes on-the-fly', function() {
scope.max = 10;
compileInput('<input type="number" ng-model="value" name="alias" max="{{max}}" />');
@@ -2934,10 +2944,20 @@ describe('input', function() {
expect(inputElm).toBeValid();
scope.max = 0;
scope.$digest(function () {
expect(inputElm).toBeInvalid();
done();
});
scope.$digest();
expect(inputElm).toBeInvalid();
scope.max = null;
scope.$digest();
expect(inputElm).toBeValid();
scope.max = '4';
scope.$digest();
expect(inputElm).toBeInvalid();
scope.max = 'abc';
scope.$digest();
expect(inputElm).toBeValid();
});
});