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

Commit b4d7733

Browse files
committed
fix(datepicker): properly set ngModel validity. Fixes #4926
1 parent c99541f commit b4d7733

File tree

3 files changed

+69
-25
lines changed

3 files changed

+69
-25
lines changed

src/components/autocomplete/autocomplete-theme.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ md-autocomplete.md-THEME_NAME-theme {
1414
}
1515
}
1616
}
17-
.md-autocomplete-suggestions-container.md-THEME_NAME-theme, {
17+
.md-autocomplete-suggestions-container.md-THEME_NAME-theme {
1818
background: '{{background-50}}';
1919
li {
2020
color: '{{background-900}}';

src/components/datepicker/datePicker.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@
307307
// the directive's isolate scope.
308308
var scope = this.$mdUtil.validateScope(this.$element) ? this.$element.scope() : null;
309309

310-
if ( scope ) {
310+
if (scope) {
311311
scope.$watch(this.$attrs['ngDisabled'], function(isDisabled) {
312312
self.setDisabled(isDisabled);
313313
});
@@ -338,11 +338,11 @@
338338
DatePickerCtrl.prototype.setErrorFlags = function() {
339339
if (this.dateUtil.isValidDate(this.date)) {
340340
if (this.dateUtil.isValidDate(this.minDate)) {
341-
this.ngModelCtrl.$error['mindate'] = this.date < this.minDate;
341+
this.ngModelCtrl.$setValidity('mindate', this.date >= this.minDate);
342342
}
343343

344344
if (this.dateUtil.isValidDate(this.maxDate)) {
345-
this.ngModelCtrl.$error['maxdate'] = this.date > this.maxDate;
345+
this.ngModelCtrl.$setValidity('maxdate', this.date <= this.maxDate);
346346
}
347347
}
348348
};

src/components/datepicker/datePicker.spec.js

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,21 @@ describe('md-date-picker', function() {
88
var initialDate = new Date(2015, FEB, 15);
99

1010
var ngElement, element, scope, pageScope, controller;
11-
var $timeout, $$rAF, $animate, $window, keyCodes, dateUtil, dateLocale;
11+
var $compile, $timeout, $$rAF, $animate, $window, keyCodes, dateUtil, dateLocale;
12+
13+
var DATEPICKER_TEMPLATE =
14+
'<md-datepicker name="birthday" ' +
15+
'md-max-date="maxDate" ' +
16+
'md-min-date="minDate" ' +
17+
'ng-model="myDate" ' +
18+
'ng-required="isRequired" ' +
19+
'ng-disabled="isDisabled">' +
20+
'</md-datepicker>';
1221

1322
beforeEach(module('material.components.datepicker', 'ngAnimateMock'));
1423

15-
beforeEach(inject(function($compile, $rootScope, $injector) {
24+
beforeEach(inject(function($rootScope, $injector) {
25+
$compile = $injector.get('$compile');
1626
$$rAF = $injector.get('$$rAF');
1727
$animate = $injector.get('$animate');
1828
$window = $injector.get('$window');
@@ -25,29 +35,33 @@ describe('md-date-picker', function() {
2535
pageScope.myDate = initialDate;
2636
pageScope.isDisabled = false;
2737

28-
var template = '<md-datepicker ' +
29-
'md-max-date="maxDate" ' +
30-
'md-min-date="minDate" ' +
31-
'ng-model="myDate" ' +
32-
'ng-required="isRequired" ' +
33-
'ng-disabled="isDisabled">' +
34-
'</md-datepicker>';
35-
ngElement = $compile(template)(pageScope);
36-
$rootScope.$apply();
37-
38-
scope = ngElement.isolateScope();
39-
controller = ngElement.controller('mdDatepicker');
40-
element = ngElement[0];
41-
38+
createDatepickerInstance(DATEPICKER_TEMPLATE);
4239
controller.closeCalendarPane();
4340
}));
4441

4542
/**
46-
* Populates the inputElement with a value and triggers the input events.
43+
* Compile and link the given template and store values for element, scope, and controller.
44+
* @param {string} template
45+
* @returns {angular.JQLite} The root compiled element.
4746
*/
47+
function createDatepickerInstance(template) {
48+
var outputElement = $compile(template)(pageScope);
49+
pageScope.$apply();
50+
51+
ngElement = outputElement[0].tagName == 'MD-DATEPICKER' ?
52+
outputElement : outputElement.find('md-datepicker');
53+
element = ngElement[0];
54+
scope = ngElement.isolateScope();
55+
controller = ngElement.controller('mdDatepicker');
56+
57+
return outputElement;
58+
}
59+
60+
/** Populates the inputElement with a value and triggers the input events. */
4861
function populateInputElement(inputString) {
4962
controller.ngInputElement.val(inputString).triggerHandler('input');
5063
$timeout.flush();
64+
pageScope.$apply();
5165
}
5266

5367
it('should set initial value from ng-model', function() {
@@ -84,28 +98,58 @@ describe('md-date-picker', function() {
8498
it('should set the `required` $error flag', function() {
8599
pageScope.isRequired = true;
86100
populateInputElement('');
87-
pageScope.$apply();
88101

89102
expect(controller.ngModelCtrl.$error['required']).toBe(true);
90103
});
91104

92105
it('should set the `mindate` $error flag', function() {
93106
pageScope.minDate = new Date(2015, JAN, 1);
94107
populateInputElement('2014-01-01');
95-
pageScope.$apply();
96108
controller.ngModelCtrl.$render();
97109

98110
expect(controller.ngModelCtrl.$error['mindate']).toBe(true);
99111
});
100112

101-
it('should set the `mindate` $error flag', function() {
113+
it('should set the `maxdate` $error flag', function() {
102114
pageScope.maxDate = new Date(2015, JAN, 1);
103115
populateInputElement('2016-01-01');
104-
pageScope.$apply();
105116
controller.ngModelCtrl.$render();
106117

107118
expect(controller.ngModelCtrl.$error['maxdate']).toBe(true);
108119
});
120+
121+
describe('inside of a form element', function() {
122+
var formCtrl;
123+
124+
beforeEach(function() {
125+
createDatepickerInstance('<form>' + DATEPICKER_TEMPLATE + '</form>');
126+
formCtrl = ngElement.controller('form');
127+
});
128+
129+
it('should set `required` $error flag on the form', function() {
130+
pageScope.isRequired = true;
131+
populateInputElement('');
132+
controller.ngModelCtrl.$render();
133+
134+
expect(formCtrl.$error['required']).toBeTruthy();
135+
});
136+
137+
it('should set `mindate` $error flag on the form', function() {
138+
pageScope.minDate = new Date(2015, JAN, 1);
139+
populateInputElement('2014-01-01');
140+
controller.ngModelCtrl.$render();
141+
142+
expect(formCtrl.$error['mindate']).toBeTruthy();
143+
});
144+
145+
it('should set `maxdate` $error flag on the form', function() {
146+
pageScope.maxDate = new Date(2015, JAN, 1);
147+
populateInputElement('2016-01-01');
148+
controller.ngModelCtrl.$render();
149+
150+
expect(formCtrl.$error['maxdate']).toBeTruthy();
151+
});
152+
});
109153
});
110154

111155
describe('input event', function() {

0 commit comments

Comments
 (0)