@@ -10,83 +10,84 @@ import {DateAdapter} from '@angular/material/core';
1010import { FactoryProvider , Optional , SkipSelf , Injectable } from '@angular/core' ;
1111import { Subject , Observable } from 'rxjs' ;
1212
13- export abstract class MatDateSelectionModel < D > {
13+ export class DateRange < D > {
14+ // DateRange should be a class with a private member.
15+ // Otherwise any object with a `start` and `end` property might be considered a
16+ // `DateRange`
17+ private _disableStructuralEquivalency : never ;
18+
19+ start : D | null ;
20+ end : D | null ;
21+
22+ constructor ( range ?: { start ?: D | null , end ?: D | null } | null ) {
23+ this . start = range && range . start || null ;
24+ this . end = range && range . end || null ;
25+ }
26+ }
27+
28+ type ExtractDateTypeFromSelection < T > = T extends DateRange < infer D > ? D : T ;
29+
30+ export abstract class MatDateSelectionModel < S , D = ExtractDateTypeFromSelection < S > > {
1431 protected _valueChangesSubject = new Subject < void > ( ) ;
1532 valueChanges : Observable < void > = this . _valueChangesSubject . asObservable ( ) ;
1633
17- constructor ( protected readonly adapter : DateAdapter < D > ) { }
34+ constructor ( protected readonly adapter : DateAdapter < D > , protected _selection : S |
35+ null = null ) { }
1836
19- destroy ( ) {
20- this . _valueChangesSubject . complete ( ) ;
21- }
22-
23- abstract add ( date : D | null ) : void ;
37+ abstract get selection ( ) : S | null ;
38+ abstract set selection ( selection : S | null ) ;
39+ abstract add ( date : D ) : void ;
2440 abstract isComplete ( ) : boolean ;
25- abstract isSame ( other : MatDateSelectionModel < D > ) : boolean ;
2641 abstract isValid ( ) : boolean ;
42+ abstract isSame ( other : MatDateSelectionModel < any , any > ) :boolean ;
2743 abstract overlaps ( range : DateRange < D > ) : boolean ;
2844}
2945
30- export interface DateRange < D > {
31- start : D | null ;
32- end : D | null ;
33- }
34-
3546/**
3647 * Concrete implementation of a MatDateSelectionModel that holds a single date.
3748 */
3849@Injectable ( )
39- export class MatSingleDateSelectionModel < D > extends MatDateSelectionModel < D > {
40- private _date : D | null = null ;
50+ export class MatSingleDateSelectionModel < D > extends MatDateSelectionModel < D , D > {
4151
4252 constructor ( adapter : DateAdapter < D > , date ?: D | null ) {
43- super ( adapter ) ;
44- this . _date = date === undefined ? null : date ;
53+ super ( adapter , date ) ;
4554 }
4655
47- add ( date : D | null ) {
48- this . _date = date ;
49- this . _valueChangesSubject . next ( ) ;
56+ get selection ( ) : D | null {
57+ return this . _selection ;
5058 }
5159
52- compareDate ( other : MatSingleDateSelectionModel < D > ) {
53- const date = this . asDate ( ) ;
54- const otherDate = other . asDate ( ) ;
55- if ( date != null && otherDate != null ) {
56- return this . adapter . compareDate ( date , otherDate ) ;
57- }
58- return date === otherDate ;
60+ set selection ( selection : D | null ) {
61+ this . _selection = selection ;
5962 }
6063
61- isComplete ( ) { return this . _date != null ; }
62-
63- isSame ( other : MatDateSelectionModel < D > ) : boolean {
64- return other instanceof MatSingleDateSelectionModel &&
65- this . adapter . sameDate ( other . asDate ( ) , this . _date ) ;
64+ add ( date : D ) {
65+ this . _selection = date ;
66+ this . _valueChangesSubject . next ( ) ;
6667 }
6768
68- isValid ( ) : boolean {
69- return this . _date != null && this . adapter . isDateInstance ( this . _date ) &&
70- this . adapter . isValid ( this . _date ) ;
69+ isComplete ( ) : boolean {
70+ return this . _selection != null ;
7171 }
7272
73- asDate ( ) : D | null {
74- return this . isValid ( ) ? this . _date : null ;
73+ isValid ( ) : boolean {
74+ return this . _selection != null && this . adapter . isDateInstance ( this . _selection ) &&
75+ this . adapter . isValid ( this . _selection ) ;
7576 }
7677
77- setDate ( date : D | null ) {
78- this . _date = date ;
79- this . _valueChangesSubject . next ( ) ;
78+ isSame ( other : MatDateSelectionModel < D > ) : boolean {
79+ return other instanceof MatSingleDateSelectionModel &&
80+ this . _selection === other . selection ;
8081 }
8182
8283 /**
8384 * Determines if the single date is within a given date range. Retuns false if either dates of
8485 * the range is null or if the selection is undefined.
8586 */
8687 overlaps ( range : DateRange < D > ) : boolean {
87- return ! ! ( this . _date && range . start && range . end &&
88- this . adapter . compareDate ( range . start , this . _date ) <= 0 &&
89- this . adapter . compareDate ( this . _date , range . end ) <= 0 ) ;
88+ return ! ! ( this . _selection && range . start && range . end &&
89+ this . adapter . compareDate ( range . start , this . _selection ) <= 0 &&
90+ this . adapter . compareDate ( this . _selection , range . end ) <= 0 ) ;
9091 }
9192}
9293
@@ -95,14 +96,20 @@ export class MatSingleDateSelectionModel<D> extends MatDateSelectionModel<D> {
9596 * a start date and an end date.
9697 */
9798@Injectable ( )
98- export class MatRangeDateSelectionModel < D > extends MatDateSelectionModel < D > {
99- private _start : D | null = null ;
100- private _end : D | null = null ;
99+ export class MatRangeDateSelectionModel < D > extends
100+ MatDateSelectionModel < DateRange < D > , D > {
101+ protected _selection : DateRange < D > ;
101102
102- constructor ( adapter : DateAdapter < D > , start ?: D | null , end ?: D | null ) {
103- super ( adapter ) ;
104- this . _start = start === undefined ? null : start ;
105- this . _end = end === undefined ? null : end ;
103+ constructor ( adapter : DateAdapter < D > , range ?: DateRange < D > | null ) {
104+ super ( adapter , range || new DateRange < D > ( ) ) ;
105+ }
106+
107+ get selection ( ) : DateRange < D > | null {
108+ return new DateRange ( this . _selection ) ;
109+ }
110+
111+ set selection ( selection : DateRange < D > | null ) {
112+ this . _selection = new DateRange ( selection ) ;
106113 }
107114
108115 /**
@@ -111,63 +118,60 @@ export class MatRangeDateSelectionModel<D> extends MatDateSelectionModel<D> {
111118 * If add is called on a complete selection, it will empty the selection and set it as the start.
112119 */
113120 add ( date : D | null ) : void {
114- if ( this . _start == null ) {
115- this . _start = date ;
116- } else if ( this . _end == null ) {
117- this . _end = date ;
121+ if ( this . _selection . start == null ) {
122+ this . _selection . start = date ;
123+ } else if ( this . _selection . end == null ) {
124+ this . _selection . end = date ;
118125 } else {
119- this . _start = date ;
120- this . _end = null ;
126+ this . _selection . start = date ;
127+ this . _selection . end = null ;
121128 }
122129
123130 this . _valueChangesSubject . next ( ) ;
124131 }
125132
126133 setRange ( start : D | null , end : D | null ) {
127- this . _start = start ;
128- this . _end = end ;
134+ this . _selection . start = start ;
135+ this . _selection . end = end ;
129136 }
130137
131138 isComplete ( ) : boolean {
132- return this . _start != null && this . _end != null ;
139+ return this . _selection && this . _selection . start != null && this . _selection . end != null ;
140+ }
141+
142+ isValid ( ) : boolean {
143+ return this . _selection . start != null && this . _selection . end != null &&
144+ this . adapter . isValid ( this . _selection . start ! ) &&
145+ this . adapter . isValid ( this . _selection . end ! ) ;
133146 }
134147
135148 isSame ( other : MatDateSelectionModel < D > ) : boolean {
136149 if ( other instanceof MatRangeDateSelectionModel ) {
137- const otherRange = other . asRange ( ) ;
138- return this . adapter . sameDate ( this . _start , otherRange . start ) &&
139- this . adapter . sameDate ( this . _end , otherRange . end ) ;
150+ return this . _selection . start === other . _selection . start &&
151+ this . _selection . end === other . _selection . end ;
140152 }
141153 return false ;
142154 }
143155
144- isValid ( ) : boolean {
145- return this . _start != null && this . _end != null &&
146- this . adapter . isValid ( this . _start ! ) && this . adapter . isValid ( this . _end ! ) ;
147- }
148-
149- asRange ( ) : DateRange < D > {
150- return {
151- start : this . _start ,
152- end : this . _end ,
153- } ;
154- }
155-
156156 /**
157157 * Returns true if the given range and the selection overlap in any way. False if otherwise, that
158158 * includes incomplete selections or ranges.
159159 */
160160 overlaps ( range : DateRange < D > ) : boolean {
161- if ( ! ( this . _start && this . _end && range . start && range . end ) ) {
161+ const selectionStart = this . _selection . start ;
162+ const selectionEnd = this . _selection . end ;
163+ const rangeStart = range . start ;
164+ const rangeEnd = range . end ;
165+ if ( ! ( selectionStart && selectionEnd && rangeStart && rangeEnd ) ) {
162166 return false ;
163167 }
164168
165169 return (
166- this . _isBetween ( range . start , this . _start , this . _end ) ||
167- this . _isBetween ( range . end , this . _start , this . _end ) ||
170+ this . _isBetween ( rangeStart , selectionStart , selectionEnd ) ||
171+ this . _isBetween ( rangeEnd , selectionStart , selectionEnd ) ||
168172 (
169- this . adapter . compareDate ( range . start , this . _start ) <= 0 &&
170- this . adapter . compareDate ( this . _end , range . end ) <= 0
173+ this . adapter . compareDate ( rangeStart , selectionStart ) <= 0 &&
174+ this . adapter . compareDate ( selectionEnd , rangeEnd ) <= 0
171175 )
172176 ) ;
173177 }
@@ -176,15 +180,3 @@ export class MatRangeDateSelectionModel<D> extends MatDateSelectionModel<D> {
176180 return this . adapter . compareDate ( from , value ) <= 0 && this . adapter . compareDate ( value , to ) <= 0 ;
177181 }
178182}
179-
180- export function MAT_SINGLE_DATE_SELECTION_MODEL_FACTORY < D > ( parent :
181- MatSingleDateSelectionModel < D > ,
182- adapter : DateAdapter < D > ) {
183- return parent || new MatSingleDateSelectionModel ( adapter ) ;
184- }
185-
186- export const MAT_SINGLE_DATE_SELECTION_MODEL_PROVIDER : FactoryProvider = {
187- provide : MatDateSelectionModel ,
188- deps : [ [ new Optional ( ) , new SkipSelf ( ) , MatDateSelectionModel ] , DateAdapter ] ,
189- useFactory : MAT_SINGLE_DATE_SELECTION_MODEL_FACTORY ,
190- } ;
0 commit comments