Skip to content

Commit

Permalink
fix(datepicker): time is modified before even selecting a date
Browse files Browse the repository at this point in the history
- `updateErrorState()` was mutating the model incorrectly and clearing the
  time to midnight when the datepicker is first interacted with, without
  selecting a date

Fixes angular#12028. Closes angular#12026.
  • Loading branch information
Splaktar committed Oct 12, 2020
1 parent 7856883 commit b406623
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/components/datepicker/js/calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@
/**
* The date that is currently focused or showing in the calendar. This will initially be set
* to the ng-model value if set, otherwise to today. It will be updated as the user navigates
* to other months. The cell corresponding to the displayDate does not necesarily always have
* to other months. The cell corresponding to the displayDate does not necessarily always have
* focus in the document (such as for cases when the user is scrolling the calendar).
* @type {Date}
*/
Expand Down
19 changes: 14 additions & 5 deletions src/components/datepicker/js/datepickerDirective.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,10 @@
*/
this.$scope = $scope;

/** @type {Date} */
/**
* This holds the model that will be used by the calendar.
* @type {Date|null|undefined}
*/
this.date = null;

/** @type {boolean} */
Expand Down Expand Up @@ -631,7 +634,12 @@
* @param {Date=} opt_date Date to check. If not given, defaults to the datepicker's model value.
*/
DatePickerCtrl.prototype.updateErrorState = function(opt_date) {
var date = opt_date || this.date;
var date;
if (opt_date) {
date = new Date(opt_date.valueOf());
} else {
date = angular.copy(this.ngModelCtrl.$modelValue);
}

// Clear any existing errors to get rid of anything that's no longer relevant.
this.clearErrorState();
Expand Down Expand Up @@ -840,7 +848,7 @@

/**
* Open the floating calendar pane.
* @param {Event} event
* @param {MouseEvent|KeyboardEvent|{target: HTMLInputElement}} event
*/
DatePickerCtrl.prototype.openCalendarPane = function(event) {
if (!this.isCalendarOpen && !this.isDisabled && !this.inputFocusedOnWindowBlur) {
Expand Down Expand Up @@ -901,7 +909,7 @@
}
}

function reset(){
function reset() {
self.isCalendarOpen = self.isOpen = false;
}
};
Expand All @@ -916,7 +924,7 @@
// Use a timeout in order to allow the calendar to be rendered, as it is gated behind an ng-if.
var self = this;
this.$mdUtil.nextTick(function() {
self.getCalendarCtrl().focusDate();
self.getCalendarCtrl().focusDate(self.date);
}, false);
};

Expand Down Expand Up @@ -1007,6 +1015,7 @@
var self = this;
var timezone = this.$mdUtil.getModelOption(this.ngModelCtrl, 'timezone');

// Update the model used by the calendar.
if (this.dateUtil.isValidDate(value) && timezone != null && value.getTimezoneOffset() >= 0) {
this.date = this.dateUtil.removeLocalTzAndReparseDate(value);
} else {
Expand Down
7 changes: 6 additions & 1 deletion src/components/datepicker/js/datepickerDirective.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,12 @@ describe('md-datepicker', function() {
createDatepickerInstance(
'<md-datepicker ng-model="myDate" ng-model-options="modelOptions"></md-datepicker>');

expect(controller.locale.formatDate).toHaveBeenCalledWith(pageScope.myDate, 'UTC');
// If running in a GMT+X timezone, formatDate will not be called with a timezone argument.
if (pageScope.myDate.getTimezoneOffset() < 0) {
expect(controller.locale.formatDate).toHaveBeenCalledWith(pageScope.myDate);
} else {
expect(controller.locale.formatDate).toHaveBeenCalledWith(pageScope.myDate, 'UTC');
}
});

it('should allow for the locale to be overwritten on a specific element', function() {
Expand Down

0 comments on commit b406623

Please sign in to comment.