@@ -30,6 +30,7 @@ import {
3030 MAT_DATE_FORMATS ,
3131 MatDateFormats ,
3232 MatDateSelectionModel ,
33+ ExtractDateTypeFromSelection ,
3334} from '@angular/material/core' ;
3435import { Subscription } from 'rxjs' ;
3536import { createMissingDateImplError } from './datepicker-errors' ;
@@ -39,13 +40,13 @@ import {createMissingDateImplError} from './datepicker-errors';
3940 * input or change event because the event may have been triggered by the user clicking on the
4041 * calendar popup. For consistency, we always use MatDatepickerInputEvent instead.
4142 */
42- export class MatDatepickerInputEvent < D > {
43+ export class MatDatepickerInputEvent < D , S = unknown > {
4344 /** The new value for the target datepicker input. */
4445 value : D | null ;
4546
4647 constructor (
4748 /** Reference to the datepicker input component that emitted the event. */
48- public target : MatDatepickerInputBase < D > ,
49+ public target : MatDatepickerInputBase < S , D > ,
4950 /** Reference to the native input element associated with the datepicker input. */
5051 public targetElement : HTMLElement ) {
5152 this . value = this . target . value ;
@@ -54,11 +55,13 @@ export class MatDatepickerInputEvent<D> {
5455
5556/** Base class for datepicker inputs. */
5657@Directive ( )
57- export abstract class MatDatepickerInputBase < D > implements ControlValueAccessor , OnDestroy ,
58- Validator {
58+ export abstract class MatDatepickerInputBase < S , D = ExtractDateTypeFromSelection < S > >
59+ implements ControlValueAccessor , OnDestroy , Validator {
5960 /** The value of the input. */
6061 @Input ( )
61- get value ( ) : D | null { return this . _model ? this . _model . selection : this . _pendingValue ; }
62+ get value ( ) : D | null {
63+ return this . _model ? this . _getValueFromModel ( this . _model . selection ) : this . _pendingValue ;
64+ }
6265 set value ( value : D | null ) {
6366 value = this . _dateAdapter . deserialize ( value ) ;
6467 this . _lastValueValid = ! value || this . _dateAdapter . isValid ( value ) ;
@@ -71,7 +74,7 @@ export abstract class MatDatepickerInputBase<D> implements ControlValueAccessor,
7174 this . _valueChange . emit ( value ) ;
7275 }
7376 }
74- protected _model : MatDateSelectionModel < D | null , D > | undefined ;
77+ protected _model : MatDateSelectionModel < S , D > | undefined ;
7578
7679 /** Whether the datepicker-input is disabled. */
7780 @Input ( )
@@ -96,12 +99,12 @@ export abstract class MatDatepickerInputBase<D> implements ControlValueAccessor,
9699 private _disabled : boolean ;
97100
98101 /** Emits when a `change` event is fired on this `<input>`. */
99- @Output ( ) readonly dateChange : EventEmitter < MatDatepickerInputEvent < D > > =
100- new EventEmitter < MatDatepickerInputEvent < D > > ( ) ;
102+ @Output ( ) readonly dateChange : EventEmitter < MatDatepickerInputEvent < D , S > > =
103+ new EventEmitter < MatDatepickerInputEvent < D , S > > ( ) ;
101104
102105 /** Emits when an `input` event is fired on this `<input>`. */
103- @Output ( ) readonly dateInput : EventEmitter < MatDatepickerInputEvent < D > > =
104- new EventEmitter < MatDatepickerInputEvent < D > > ( ) ;
106+ @Output ( ) readonly dateInput : EventEmitter < MatDatepickerInputEvent < D , S > > =
107+ new EventEmitter < MatDatepickerInputEvent < D , S > > ( ) ;
105108
106109 /** Emits when the value changes (either due to user input or programmatic change). */
107110 _valueChange = new EventEmitter < D | null > ( ) ;
@@ -129,7 +132,7 @@ export abstract class MatDatepickerInputBase<D> implements ControlValueAccessor,
129132 null : { 'matDatepickerParse' : { 'text' : this . _elementRef . nativeElement . value } } ;
130133 }
131134
132- protected _registerModel ( model : MatDateSelectionModel < D | null , D > ) : void {
135+ protected _registerModel ( model : MatDateSelectionModel < S , D > ) : void {
133136 this . _model = model ;
134137 this . _valueChangesSubscription . unsubscribe ( ) ;
135138
@@ -139,11 +142,12 @@ export abstract class MatDatepickerInputBase<D> implements ControlValueAccessor,
139142
140143 this . _valueChangesSubscription = this . _model . selectionChanged . subscribe ( event => {
141144 if ( event . source !== this ) {
142- this . _cvaOnChange ( event . selection ) ;
145+ const value = this . _getValueFromModel ( event . selection ) ;
146+ this . _cvaOnChange ( value ) ;
143147 this . _onTouched ( ) ;
144148 this . dateInput . emit ( new MatDatepickerInputEvent ( this , this . _elementRef . nativeElement ) ) ;
145149 this . dateChange . emit ( new MatDatepickerInputEvent ( this , this . _elementRef . nativeElement ) ) ;
146- this . _formatValue ( event . selection ) ;
150+ this . _formatValue ( value ) ;
147151 }
148152 } ) ;
149153 }
@@ -152,7 +156,10 @@ export abstract class MatDatepickerInputBase<D> implements ControlValueAccessor,
152156 protected abstract _openPopup ( ) : void ;
153157
154158 /** Assigns a value to the input's model. */
155- protected abstract _assignModelValue ( model : D | null ) : void ;
159+ protected abstract _assignValueToModel ( model : D | null ) : void ;
160+
161+ /** Converts a value from the model into a native value for the input. */
162+ protected abstract _getValueFromModel ( modelValue : S ) : D | null ;
156163
157164 /** The combined form control validator for this input. */
158165 protected abstract _validator : ValidatorFn | null ;
@@ -272,7 +279,7 @@ export abstract class MatDatepickerInputBase<D> implements ControlValueAccessor,
272279 // We may get some incoming values before the model was
273280 // assigned. Save the value so that we can assign it later.
274281 if ( this . _model ) {
275- this . _assignModelValue ( value ) ;
282+ this . _assignValueToModel ( value ) ;
276283 this . _pendingValue = null ;
277284 } else {
278285 this . _pendingValue = value ;
0 commit comments