New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(datepicker): validate that input actually parses #5711
Conversation
@@ -192,6 +192,10 @@ export class NativeDateAdapter extends DateAdapter<Date> { | |||
].join('-'); | |||
} | |||
|
|||
isDateObject(value: any) { | |||
return value instanceof Date; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add unit test for this?
@@ -99,12 +99,14 @@ export class MdDatepickerInput<D> implements AfterContentInit, ControlValueAcces | |||
this._dateFormats.parse.dateInput); | |||
} | |||
set value(value: D | null) { | |||
let date = this._dateAdapter.parse(value, this._dateFormats.parse.dateInput); | |||
if (value != null && !this._dateAdapter.isDateObject(value)) { | |||
throw new Error('Datepicker: value not recognized as a date object by DateAdapter.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hot tip: with Error
you don't need new
(just throw Error('...')
)
comments addressed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Caretaker note: one google app already had an invalid value, will need to fix |
un-lgtm'ing this so I can reconcile with what we talked about in #4978 |
@jelbourn Changed this PR a bit based on the discussion @kara and I had about #4978. I think just throwing an error like I was doing before is problematic if we want to do parse validation. Couple of questions:
|
@@ -192,6 +197,16 @@ export class NativeDateAdapter extends DateAdapter<Date> { | |||
].join('-'); | |||
} | |||
|
|||
isValidDate(value: any) { | |||
if (value == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jelbourn It kind of feels wrong that people extending DateAdapter
even have the ability to say "null is invalid" maybe an indicator that I should move all the null checks into the datepicker code itself, WDYT?
9fd24e0
to
34bc1be
Compare
Ok answering my own questions:
|
} | ||
|
||
format(date: Date, displayFormat: Object): string { | ||
if (!this.isValid(date)) { | ||
return 'INVALID DATE'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what the best thing to do here is (probably not this). Datepicker should never call format on an invalid date, but someone could in their code, maybe just throw an error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throwing an error seems reasonable to me
abstract isValid(date: D): boolean; | ||
|
||
/** | ||
* @param {obj} The object to check. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Omit braces on obj
*/ | ||
getValidDateOrNull(obj: any): D | null { | ||
return (this.isDateInstance(obj) && this.isValid(obj)) ? obj : null; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be be more appropriate to have this in the component code than in the adapter?
comments adressed, also meant to include a demo link: https://mmalerba-demo2.firebaseapp.com/datepicker |
@kara demo behavior is still a little different from how number inputs work (compare demo link above with this plunker) http://plnkr.co/edit/GoutPJd2AXx7KPD4d0XB?p=preview any advice on how to make it a little closer to what number input does? |
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).
@kara @jelbourn Ok I think I've finally gotten the behavior exactly how I want it now. The material input and the native input under the "Result" section of this demo are wired up to the same |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just nits
it('should parse invalid value as invalid', () => { | ||
let d = adapter.parse('hello'); | ||
expect(d).not.toBeNull(); | ||
expect(adapter.isDateInstance(d)).toBe(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: add a failure message here? Seems odd without context that 'hello' would be a Date instance. e.g. Expected string to be fed through Date.parse()
it('should throw when given wrong data type', () => { | ||
testComponent.date = '1/1/2017' as any; | ||
|
||
expect(() => fixture.detectChanges()).toThrow(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Add a regex to make this clear which error should surface? e.g. toThrowError(new RegExp(...)
} | ||
|
||
format(date: Date, displayFormat: Object): string { | ||
if (!this.isValid(date)) { | ||
return 'INVALID DATE'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throwing an error seems reasonable to me
Comments addressed |
LGTM |
I also get this when I was not getting this before date format is 2017-08-02T00:00:00 |
@mmalerba in your demo, validation is passing if I type 34 and I get 1/1/2034 |
@jbojcic1 that's because |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
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
, orformControl
).BREAKING CHNAGE:
DateAdapter
subclasses must now provide an implementation forisValidDate
fixes #5417
fixes #4978