@@ -10,83 +10,84 @@ import {DateAdapter} from '@angular/material/core';
10
10
import { FactoryProvider , Optional , SkipSelf , Injectable } from '@angular/core' ;
11
11
import { Subject , Observable } from 'rxjs' ;
12
12
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 > > {
14
31
protected _valueChangesSubject = new Subject < void > ( ) ;
15
32
valueChanges : Observable < void > = this . _valueChangesSubject . asObservable ( ) ;
16
33
17
- constructor ( protected readonly adapter : DateAdapter < D > ) { }
34
+ constructor ( protected readonly adapter : DateAdapter < D > , protected _selection : S |
35
+ null = null ) { }
18
36
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 ;
24
40
abstract isComplete ( ) : boolean ;
25
- abstract isSame ( other : MatDateSelectionModel < D > ) : boolean ;
26
41
abstract isValid ( ) : boolean ;
42
+ abstract isSame ( other : MatDateSelectionModel < any , any > ) :boolean ;
27
43
abstract overlaps ( range : DateRange < D > ) : boolean ;
28
44
}
29
45
30
- export interface DateRange < D > {
31
- start : D | null ;
32
- end : D | null ;
33
- }
34
-
35
46
/**
36
47
* Concrete implementation of a MatDateSelectionModel that holds a single date.
37
48
*/
38
49
@Injectable ( )
39
- export class MatSingleDateSelectionModel < D > extends MatDateSelectionModel < D > {
40
- private _date : D | null = null ;
50
+ export class MatSingleDateSelectionModel < D > extends MatDateSelectionModel < D , D > {
41
51
42
52
constructor ( adapter : DateAdapter < D > , date ?: D | null ) {
43
- super ( adapter ) ;
44
- this . _date = date === undefined ? null : date ;
53
+ super ( adapter , date ) ;
45
54
}
46
55
47
- add ( date : D | null ) {
48
- this . _date = date ;
49
- this . _valueChangesSubject . next ( ) ;
56
+ get selection ( ) : D | null {
57
+ return this . _selection ;
50
58
}
51
59
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 ;
59
62
}
60
63
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 ( ) ;
66
67
}
67
68
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 ;
71
71
}
72
72
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 ) ;
75
76
}
76
77
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 ;
80
81
}
81
82
82
83
/**
83
84
* Determines if the single date is within a given date range. Retuns false if either dates of
84
85
* the range is null or if the selection is undefined.
85
86
*/
86
87
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 ) ;
90
91
}
91
92
}
92
93
@@ -95,14 +96,20 @@ export class MatSingleDateSelectionModel<D> extends MatDateSelectionModel<D> {
95
96
* a start date and an end date.
96
97
*/
97
98
@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 > ;
101
102
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 ) ;
106
113
}
107
114
108
115
/**
@@ -111,63 +118,60 @@ export class MatRangeDateSelectionModel<D> extends MatDateSelectionModel<D> {
111
118
* If add is called on a complete selection, it will empty the selection and set it as the start.
112
119
*/
113
120
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 ;
118
125
} else {
119
- this . _start = date ;
120
- this . _end = null ;
126
+ this . _selection . start = date ;
127
+ this . _selection . end = null ;
121
128
}
122
129
123
130
this . _valueChangesSubject . next ( ) ;
124
131
}
125
132
126
133
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 ;
129
136
}
130
137
131
138
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 ! ) ;
133
146
}
134
147
135
148
isSame ( other : MatDateSelectionModel < D > ) : boolean {
136
149
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 ;
140
152
}
141
153
return false ;
142
154
}
143
155
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
-
156
156
/**
157
157
* Returns true if the given range and the selection overlap in any way. False if otherwise, that
158
158
* includes incomplete selections or ranges.
159
159
*/
160
160
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 ) ) {
162
166
return false ;
163
167
}
164
168
165
169
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 ) ||
168
172
(
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
171
175
)
172
176
) ;
173
177
}
@@ -176,15 +180,3 @@ export class MatRangeDateSelectionModel<D> extends MatDateSelectionModel<D> {
176
180
return this . adapter . compareDate ( from , value ) <= 0 && this . adapter . compareDate ( value , to ) <= 0 ;
177
181
}
178
182
}
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