Skip to content

Commit

Permalink
fix(ngModel): revalidate the model when min/max expression values cha…
Browse files Browse the repository at this point in the history
…nge 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 angular#2404
  • Loading branch information
matsko committed Sep 3, 2014
1 parent b474c36 commit a707a81
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 14 deletions.
24 changes: 22 additions & 2 deletions src/ng/directive/input.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
}
}

Expand Down
44 changes: 32 additions & 12 deletions test/ng/directive/inputSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
});

Expand All @@ -2926,18 +2936,28 @@ 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}}" />');

changeInputValueTo('5');
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();
});
});

Expand Down

0 comments on commit a707a81

Please sign in to comment.