Skip to content

Commit bde0170

Browse files
committed
fix(datepicker): throw when value is set to invalid type
BREAKING CHANGE: You must now use an actual Date object rather than a string when setting the value of the datepicker programmatically (through value, ngModel, or formControl).
1 parent e8005ec commit bde0170

File tree

4 files changed

+26
-5
lines changed

4 files changed

+26
-5
lines changed

src/lib/core/datetime/date-adapter.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,13 @@ export abstract class DateAdapter<D> {
156156
*/
157157
abstract getISODateString(date: D): string;
158158

159+
/**
160+
* Checks whether the given value is a date object of type `D`.
161+
* @param value The value to check.
162+
* @returns Whether the value is a date object of type `D`.
163+
*/
164+
abstract isDateObject(value: any): boolean;
165+
159166
/**
160167
* Sets the locale used for all dates.
161168
* @param locale The new locale.

src/lib/core/datetime/native-date-adapter.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ export class NativeDateAdapter extends DateAdapter<Date> {
192192
].join('-');
193193
}
194194

195+
isDateObject(value: any) {
196+
return value instanceof Date;
197+
}
198+
195199
/** Creates a date but allows the month and date to overflow. */
196200
private _createDateWithOverflow(year: number, month: number, date: number) {
197201
let result = new Date(year, month, date);

src/lib/datepicker/datepicker-input.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,14 @@ export class MdDatepickerInput<D> implements AfterContentInit, ControlValueAcces
116116
this._dateFormats.parse.dateInput);
117117
}
118118
set value(value: D | null) {
119-
let date = this._dateAdapter.parse(value, this._dateFormats.parse.dateInput);
119+
if (value != null && !this._dateAdapter.isDateObject(value)) {
120+
throw new Error('Datepicker: value not recognized as a date object by DateAdapter.');
121+
}
120122
let oldDate = this.value;
121123
this._renderer.setProperty(this._elementRef.nativeElement, 'value',
122-
date ? this._dateAdapter.format(date, this._dateFormats.display.dateInput) : '');
123-
if (!this._dateAdapter.sameDate(oldDate, date)) {
124-
this._valueChange.emit(date);
124+
value ? this._dateAdapter.format(value, this._dateFormats.display.dateInput) : '');
125+
if (!this._dateAdapter.sameDate(oldDate, value)) {
126+
this._valueChange.emit(value);
125127
}
126128
}
127129

src/lib/datepicker/datepicker.spec.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,14 @@ describe('MdDatepicker', () => {
223223
expect(ownedElement).not.toBeNull();
224224
expect((ownedElement as Element).tagName.toLowerCase()).toBe('md-calendar');
225225
});
226+
227+
it('should throw when given wrong data type', () => {
228+
testComponent.date = '1/1/2017' as any;
229+
230+
expect(() => fixture.detectChanges()).toThrow();
231+
232+
testComponent.date = null;
233+
});
226234
});
227235

228236
describe('datepicker with too many inputs', () => {
@@ -876,7 +884,7 @@ describe('MdDatepicker', () => {
876884
class StandardDatepicker {
877885
touch = false;
878886
disabled = false;
879-
date = new Date(2020, JAN, 1);
887+
date: Date | null = new Date(2020, JAN, 1);
880888
@ViewChild('d') datepicker: MdDatepicker<Date>;
881889
@ViewChild(MdDatepickerInput) datepickerInput: MdDatepickerInput<Date>;
882890
}

0 commit comments

Comments
 (0)