@@ -112,36 +112,41 @@ export class MdDatepickerInput<D> implements AfterContentInit, ControlValueAcces
112112 /** The value of the input. */
113113 @Input ( )
114114 get value ( ) : D | null {
115- return this . _dateAdapter . parse ( this . _elementRef . nativeElement . value ,
116- this . _dateFormats . parse . dateInput ) ;
115+ return this . _getValidDateOrNull ( this . _dateAdapter . parse (
116+ this . _elementRef . nativeElement . value , 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 . isDateInstance ( value ) ) {
120+ throw Error ( 'Datepicker: value not recognized as a date object by DateAdapter.' ) ;
121+ }
122+ this . _lastValueValid = ! value || this . _dateAdapter . isValid ( value ) ;
123+ value = this . _getValidDateOrNull ( value ) ;
124+
120125 let oldDate = this . value ;
121126 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 ) ;
127+ value ? this . _dateAdapter . format ( value , this . _dateFormats . display . dateInput ) : '' ) ;
128+ if ( ! this . _dateAdapter . sameDate ( oldDate , value ) ) {
129+ this . _valueChange . emit ( value ) ;
125130 }
126131 }
127132
128133 /** The minimum valid date. */
129134 @Input ( )
130- get min ( ) : D { return this . _min ; }
131- set min ( value : D ) {
135+ get min ( ) : D | null { return this . _min ; }
136+ set min ( value : D | null ) {
132137 this . _min = value ;
133138 this . _validatorOnChange ( ) ;
134139 }
135- private _min : D ;
140+ private _min : D | null ;
136141
137142 /** The maximum valid date. */
138143 @Input ( )
139- get max ( ) : D { return this . _max ; }
140- set max ( value : D ) {
144+ get max ( ) : D | null { return this . _max ; }
145+ set max ( value : D | null ) {
141146 this . _max = value ;
142147 this . _validatorOnChange ( ) ;
143148 }
144- private _max : D ;
149+ private _max : D | null ;
145150
146151 /** Whether the datepicker-input is disabled. */
147152 @Input ( )
@@ -168,6 +173,12 @@ export class MdDatepickerInput<D> implements AfterContentInit, ControlValueAcces
168173
169174 private _datepickerSubscription : Subscription ;
170175
176+ /** The form control validator for whether the input parses. */
177+ private _parseValidator : ValidatorFn = ( ) : ValidationErrors | null => {
178+ return this . _lastValueValid ?
179+ null : { 'mdDatepickerParse' : { 'text' : this . _elementRef . nativeElement . value } } ;
180+ }
181+
171182 /** The form control validator for the min date. */
172183 private _minValidator : ValidatorFn = ( control : AbstractControl ) : ValidationErrors | null => {
173184 return ( ! this . min || ! control . value ||
@@ -190,7 +201,11 @@ export class MdDatepickerInput<D> implements AfterContentInit, ControlValueAcces
190201
191202 /** The combined form control validator for this input. */
192203 private _validator : ValidatorFn | null =
193- Validators . compose ( [ this . _minValidator , this . _maxValidator , this . _filterValidator ] ) ;
204+ Validators . compose (
205+ [ this . _parseValidator , this . _minValidator , this . _maxValidator , this . _filterValidator ] ) ;
206+
207+ /** Whether the last value set on the input was valid. */
208+ private _lastValueValid = false ;
194209
195210 constructor (
196211 private _elementRef : ElementRef ,
@@ -270,6 +285,8 @@ export class MdDatepickerInput<D> implements AfterContentInit, ControlValueAcces
270285
271286 _onInput ( value : string ) {
272287 let date = this . _dateAdapter . parse ( value , this . _dateFormats . parse . dateInput ) ;
288+ this . _lastValueValid = ! date || this . _dateAdapter . isValid ( date ) ;
289+ date = this . _getValidDateOrNull ( date ) ;
273290 this . _cvaOnChange ( date ) ;
274291 this . _valueChange . emit ( date ) ;
275292 this . dateInput . emit ( new MdDatepickerInputEvent ( this , this . _elementRef . nativeElement ) ) ;
@@ -278,4 +295,12 @@ export class MdDatepickerInput<D> implements AfterContentInit, ControlValueAcces
278295 _onChange ( ) {
279296 this . dateChange . emit ( new MdDatepickerInputEvent ( this , this . _elementRef . nativeElement ) ) ;
280297 }
298+
299+ /**
300+ * @param obj The object to check.
301+ * @returns The given object if it is both a date instance and valid, otherwise null.
302+ */
303+ private _getValidDateOrNull ( obj : any ) : D | null {
304+ return ( this . _dateAdapter . isDateInstance ( obj ) && this . _dateAdapter . isValid ( obj ) ) ? obj : null ;
305+ }
281306}
0 commit comments