Skip to content

Commit 603dfa4

Browse files
crisbetotinayuangao
authored andcommitted
fix(datepicker): reformat valid values on blur (#10777)
Formats valid values, that were typed into the datepicker, when the user blur the input. Invalid values won't be changed. Fixes #10645.
1 parent 8acd5a1 commit 603dfa4

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

src/lib/datepicker/datepicker-input.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export class MatDatepickerInputEvent<D> {
8787
'[disabled]': 'disabled',
8888
'(input)': '_onInput($event.target.value)',
8989
'(change)': '_onChange()',
90-
'(blur)': '_onTouched()',
90+
'(blur)': '_onBlur()',
9191
'(keydown)': '_onKeydown($event)',
9292
},
9393
exportAs: 'matDatepickerInput',
@@ -123,10 +123,10 @@ export class MatDatepickerInput<D> implements AfterContentInit, ControlValueAcce
123123
value = this._dateAdapter.deserialize(value);
124124
this._lastValueValid = !value || this._dateAdapter.isValid(value);
125125
value = this._getValidDateOrNull(value);
126-
let oldDate = this.value;
126+
const oldDate = this.value;
127127
this._value = value;
128-
this._elementRef.nativeElement.value =
129-
value ? this._dateAdapter.format(value, this._dateFormats.display.dateInput) : '';
128+
this._formatValue(value);
129+
130130
if (!this._dateAdapter.sameDate(oldDate, value)) {
131131
this._valueChange.emit(value);
132132
}
@@ -343,6 +343,22 @@ export class MatDatepickerInput<D> implements AfterContentInit, ControlValueAcce
343343
return this._formField ? this._formField.color : undefined;
344344
}
345345

346+
/** Handles blur events on the input. */
347+
_onBlur() {
348+
// Reformat the input only if we have a valid value.
349+
if (this.value) {
350+
this._formatValue(this.value);
351+
}
352+
353+
this._onTouched();
354+
}
355+
356+
/** Formats a value and sets it on the input element. */
357+
private _formatValue(value: D | null) {
358+
this._elementRef.nativeElement.value =
359+
value ? this._dateAdapter.format(value, this._dateFormats.display.dateInput) : '';
360+
}
361+
346362
/**
347363
* @param obj The object to check.
348364
* @returns The given object if it is both a date instance and valid, otherwise null.

src/lib/datepicker/datepicker.spec.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,38 @@ describe('MatDatepicker', () => {
663663
expect(inputEl.classList).toContain('ng-touched');
664664
});
665665

666+
it('should reformat the input value on blur', () => {
667+
if (SUPPORTS_INTL) {
668+
// Skip this test if the internationalization API is not supported in the current
669+
// browser. Browsers like Safari 9 do not support the "Intl" API.
670+
return;
671+
}
672+
673+
const inputEl = fixture.debugElement.query(By.css('input')).nativeElement;
674+
675+
inputEl.value = '2001-01-01';
676+
dispatchFakeEvent(inputEl, 'input');
677+
fixture.detectChanges();
678+
679+
dispatchFakeEvent(inputEl, 'blur');
680+
fixture.detectChanges();
681+
682+
expect(inputEl.value).toBe('1/1/2001');
683+
});
684+
685+
it('should not reformat invalid dates on blur', () => {
686+
const inputEl = fixture.debugElement.query(By.css('input')).nativeElement;
687+
688+
inputEl.value = 'very-valid-date';
689+
dispatchFakeEvent(inputEl, 'input');
690+
fixture.detectChanges();
691+
692+
dispatchFakeEvent(inputEl, 'blur');
693+
fixture.detectChanges();
694+
695+
expect(inputEl.value).toBe('very-valid-date');
696+
});
697+
666698
it('should mark input touched on calendar selection', fakeAsync(() => {
667699
let inputEl = fixture.debugElement.query(By.css('input')).nativeElement;
668700

0 commit comments

Comments
 (0)