Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit b350283

Browse files
committed
fix(ngModel): revalidate the model when min/max expression values change for date inputs
Closes #6755
1 parent 25541c1 commit b350283

File tree

2 files changed

+155
-39
lines changed

2 files changed

+155
-39
lines changed

src/ng/directive/input.js

+18-4
Original file line numberDiff line numberDiff line change
@@ -1082,16 +1082,30 @@ function createDateInputType(type, regexp, parseDate, format) {
10821082
return '';
10831083
});
10841084

1085-
if (attr.min) {
1085+
if (attr.min || attr.ngMin) {
1086+
var minVal;
10861087
ctrl.$validators.min = function(value) {
1087-
return ctrl.$isEmpty(value) || isUndefined(attr.min) || parseDate(value) >= parseDate(attr.min);
1088+
return ctrl.$isEmpty(value) || isUndefined(minVal) || parseDate(value) >= minVal;
10881089
};
1090+
attr.$observe('min', function(val) {
1091+
minVal = parseObservedDateValue(val);
1092+
ctrl.$validate();
1093+
});
10891094
}
10901095

1091-
if (attr.max) {
1096+
if (attr.max || attr.ngMax) {
1097+
var maxVal;
10921098
ctrl.$validators.max = function(value) {
1093-
return ctrl.$isEmpty(value) || isUndefined(attr.max) || parseDate(value) <= parseDate(attr.max);
1099+
return ctrl.$isEmpty(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;
10941100
};
1101+
attr.$observe('max', function(val) {
1102+
maxVal = parseObservedDateValue(val);
1103+
ctrl.$validate();
1104+
});
1105+
}
1106+
1107+
function parseObservedDateValue(val) {
1108+
return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;
10951109
}
10961110
};
10971111
}

test/ng/directive/inputSpec.js

+137-35
Original file line numberDiff line numberDiff line change
@@ -2063,9 +2063,12 @@ describe('input', function() {
20632063
});
20642064

20652065
describe('min', function (){
2066-
beforeEach(function (){
2067-
compileInput('<input type="month" ng-model="value" name="alias" min="2013-01" />');
2068-
});
2066+
var scope;
2067+
beforeEach(inject(function ($rootScope){
2068+
scope = $rootScope;
2069+
$rootScope.minVal = '2013-01';
2070+
compileInput('<input type="month" ng-model="value" name="alias" min="{{ minVal }}" />');
2071+
}));
20692072

20702073
it('should invalidate', function (){
20712074
changeInputValueTo('2012-12');
@@ -2080,12 +2083,27 @@ describe('input', function() {
20802083
expect(+scope.value).toBe(+new Date(2013, 6, 1));
20812084
expect(scope.form.alias.$error.min).toBeFalsy();
20822085
});
2086+
2087+
it('should revalidate when the min value changes', function (){
2088+
changeInputValueTo('2013-07');
2089+
expect(inputElm).toBeValid();
2090+
expect(scope.form.alias.$error.min).toBeFalsy();
2091+
2092+
scope.minVal = '2014-01';
2093+
scope.$digest();
2094+
2095+
expect(inputElm).toBeInvalid();
2096+
expect(scope.form.alias.$error.min).toBeTruthy();
2097+
});
20832098
});
20842099

20852100
describe('max', function(){
2086-
beforeEach(function (){
2087-
compileInput('<input type="month" ng-model="value" name="alias" max="2013-01" />');
2088-
});
2101+
var scope;
2102+
beforeEach(inject(function ($rootScope){
2103+
scope = $rootScope;
2104+
$rootScope.maxVal = '2013-01';
2105+
compileInput('<input type="month" ng-model="value" name="alias" max="{{ maxVal }}" />');
2106+
}));
20892107

20902108
it('should validate', function (){
20912109
changeInputValueTo('2012-03');
@@ -2100,6 +2118,18 @@ describe('input', function() {
21002118
expect(scope.value).toBeUndefined();
21012119
expect(scope.form.alias.$error.max).toBeTruthy();
21022120
});
2121+
2122+
it('should revalidate when the max value changes', function (){
2123+
changeInputValueTo('2012-07');
2124+
expect(inputElm).toBeValid();
2125+
expect(scope.form.alias.$error.max).toBeFalsy();
2126+
2127+
scope.maxVal = '2012-01';
2128+
scope.$digest();
2129+
2130+
expect(inputElm).toBeInvalid();
2131+
expect(scope.form.alias.$error.max).toBeTruthy();
2132+
});
21032133
});
21042134
});
21052135

@@ -2204,9 +2234,12 @@ describe('input', function() {
22042234
});
22052235

22062236
describe('min', function (){
2207-
beforeEach(function (){
2208-
compileInput('<input type="week" ng-model="value" name="alias" min="2013-W01" />');
2209-
});
2237+
var scope;
2238+
beforeEach(inject(function ($rootScope){
2239+
scope = $rootScope;
2240+
$rootScope.minVal = '2013-W01';
2241+
compileInput('<input type="week" ng-model="value" name="alias" min="{{ minVal }}" />');
2242+
}));
22102243

22112244
it('should invalidate', function (){
22122245
changeInputValueTo('2012-W12');
@@ -2221,12 +2254,26 @@ describe('input', function() {
22212254
expect(+scope.value).toBe(+new Date(2013, 0, 17));
22222255
expect(scope.form.alias.$error.min).toBeFalsy();
22232256
});
2257+
2258+
it('should revalidate when the min value changes', function (){
2259+
changeInputValueTo('2013-W03');
2260+
expect(inputElm).toBeValid();
2261+
expect(scope.form.alias.$error.min).toBeFalsy();
2262+
2263+
scope.minVal = '2014-W01';
2264+
scope.$digest();
2265+
2266+
expect(inputElm).toBeInvalid();
2267+
expect(scope.form.alias.$error.min).toBeTruthy();
2268+
});
22242269
});
22252270

22262271
describe('max', function(){
2227-
beforeEach(function (){
2228-
compileInput('<input type="week" ng-model="value" name="alias" max="2013-W01" />');
2229-
});
2272+
beforeEach(inject(function ($rootScope){
2273+
$rootScope.maxVal = '2013-W01';
2274+
scope = $rootScope;
2275+
compileInput('<input type="week" ng-model="value" name="alias" max="{{ maxVal }}" />');
2276+
}));
22302277

22312278
it('should validate', function (){
22322279
changeInputValueTo('2012-W01');
@@ -2241,6 +2288,18 @@ describe('input', function() {
22412288
expect(scope.value).toBeUndefined();
22422289
expect(scope.form.alias.$error.max).toBeTruthy();
22432290
});
2291+
2292+
it('should revalidate when the max value changes', function (){
2293+
changeInputValueTo('2012-W03');
2294+
expect(inputElm).toBeValid();
2295+
expect(scope.form.alias.$error.max).toBeFalsy();
2296+
2297+
scope.maxVal = '2012-W01';
2298+
scope.$digest();
2299+
2300+
expect(inputElm).toBeInvalid();
2301+
expect(scope.form.alias.$error.max).toBeTruthy();
2302+
});
22442303
});
22452304
});
22462305

@@ -2363,9 +2422,12 @@ describe('input', function() {
23632422
});
23642423

23652424
describe('min', function (){
2366-
beforeEach(function (){
2367-
compileInput('<input type="datetime-local" ng-model="value" name="alias" min="2000-01-01T12:30:00" />');
2368-
});
2425+
var scope;
2426+
beforeEach(inject(function ($rootScope){
2427+
$rootScope.minVal = '2000-01-01T12:30:00';
2428+
scope = $rootScope;
2429+
compileInput('<input type="datetime-local" ng-model="value" name="alias" min="{{ minVal }}" />');
2430+
}));
23692431

23702432
it('should invalidate', function (){
23712433
changeInputValueTo('1999-12-31T01:02:00');
@@ -2380,12 +2442,27 @@ describe('input', function() {
23802442
expect(+scope.value).toBe(+new Date(2000, 0, 1, 23, 2, 0));
23812443
expect(scope.form.alias.$error.min).toBeFalsy();
23822444
});
2445+
2446+
it('should revalidate when the min value changes', function (){
2447+
changeInputValueTo('2000-02-01T01:02:00');
2448+
expect(inputElm).toBeValid();
2449+
expect(scope.form.alias.$error.min).toBeFalsy();
2450+
2451+
scope.minVal = '2010-01-01T01:02:00';
2452+
scope.$digest();
2453+
2454+
expect(inputElm).toBeInvalid();
2455+
expect(scope.form.alias.$error.min).toBeTruthy();
2456+
});
23832457
});
23842458

23852459
describe('max', function (){
2386-
beforeEach(function (){
2387-
compileInput('<input type="datetime-local" ng-model="value" name="alias" max="2019-01-01T01:02:00" />');
2388-
});
2460+
var scope;
2461+
beforeEach(inject(function ($rootScope){
2462+
$rootScope.maxVal = '2019-01-01T01:02:00';
2463+
scope = $rootScope;
2464+
compileInput('<input type="datetime-local" ng-model="value" name="alias" max="{{ maxVal }}" />');
2465+
}));
23892466

23902467
it('should invalidate', function (){
23912468
changeInputValueTo('2019-12-31T01:02:00');
@@ -2400,6 +2477,18 @@ describe('input', function() {
24002477
expect(+scope.value).toBe(+new Date(2000, 0, 1, 1, 2, 0));
24012478
expect(scope.form.alias.$error.max).toBeFalsy();
24022479
});
2480+
2481+
it('should revalidate when the max value changes', function (){
2482+
changeInputValueTo('2000-02-01T01:02:00');
2483+
expect(inputElm).toBeValid();
2484+
expect(scope.form.alias.$error.max).toBeFalsy();
2485+
2486+
scope.maxVal = '2000-01-01T01:02:00';
2487+
scope.$digest();
2488+
2489+
expect(inputElm).toBeInvalid();
2490+
expect(scope.form.alias.$error.max).toBeTruthy();
2491+
});
24032492
});
24042493

24052494
it('should validate even if max value changes on-the-fly', function(done) {
@@ -2550,9 +2639,12 @@ describe('input', function() {
25502639
});
25512640

25522641
describe('min', function (){
2553-
beforeEach(function (){
2554-
compileInput('<input type="time" ng-model="value" name="alias" min="09:30:00" />');
2555-
});
2642+
var scope;
2643+
beforeEach(inject(function ($rootScope){
2644+
$rootScope.minVal = '09:30:00';
2645+
scope = $rootScope;
2646+
compileInput('<input type="time" ng-model="value" name="alias" min="{{ minVal }}" />');
2647+
}));
25562648

25572649
it('should invalidate', function (){
25582650
changeInputValueTo('01:02:00');
@@ -2567,6 +2659,18 @@ describe('input', function() {
25672659
expect(+scope.value).toBe(+new Date(1970, 0, 1, 23, 2, 0));
25682660
expect(scope.form.alias.$error.min).toBeFalsy();
25692661
});
2662+
2663+
it('should revalidate when the min value changes', function (){
2664+
changeInputValueTo('23:02:00');
2665+
expect(inputElm).toBeValid();
2666+
expect(scope.form.alias.$error.min).toBeFalsy();
2667+
2668+
scope.minVal = '23:55:00';
2669+
scope.$digest();
2670+
2671+
expect(inputElm).toBeInvalid();
2672+
expect(scope.form.alias.$error.min).toBeTruthy();
2673+
});
25702674
});
25712675

25722676
describe('max', function (){
@@ -2589,32 +2693,30 @@ describe('input', function() {
25892693
});
25902694
});
25912695

2592-
it('should validate even if max value changes on-the-fly', function(done) {
2593-
scope.max = '21:02:00';
2696+
it('should validate even if max value changes on-the-fly', function() {
2697+
scope.max = '4:02:00';
25942698
compileInput('<input type="time" ng-model="value" name="alias" max="{{max}}" />');
25952699

2596-
changeInputValueTo('22:34:00');
2700+
changeInputValueTo('05:34:00');
25972701
expect(inputElm).toBeInvalid();
25982702

2599-
scope.max = '12:34:00';
2600-
scope.$digest(function () {
2601-
expect(inputElm).toBeValid();
2602-
done();
2603-
});
2703+
scope.max = '06:34:00';
2704+
scope.$digest();
2705+
2706+
expect(inputElm).toBeValid();
26042707
});
26052708

2606-
it('should validate even if min value changes on-the-fly', function(done) {
2709+
it('should validate even if min value changes on-the-fly', function() {
26072710
scope.min = '08:45:00';
26082711
compileInput('<input type="time" ng-model="value" name="alias" min="{{min}}" />');
26092712

26102713
changeInputValueTo('06:15:00');
26112714
expect(inputElm).toBeInvalid();
26122715

2613-
scope.min = '13:50:00';
2614-
scope.$digest(function () {
2615-
expect(inputElm).toBeValid();
2616-
done();
2617-
});
2716+
scope.min = '05:50:00';
2717+
scope.$digest();
2718+
2719+
expect(inputElm).toBeValid();
26182720
});
26192721
});
26202722

0 commit comments

Comments
 (0)