Skip to content

Commit 23866f2

Browse files
committed
incoporate new type definition
1 parent 0a0ea04 commit 23866f2

File tree

2 files changed

+61
-133
lines changed

2 files changed

+61
-133
lines changed

src/material/core/datetime/date-selection-model.ts

Lines changed: 50 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -10,83 +10,58 @@ import {DateAdapter} from '@angular/material/core';
1010
import {FactoryProvider, Optional, SkipSelf, Injectable} from '@angular/core';
1111
import {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 _x: never;
18+
19+
start: D | null;
20+
end: D | null;
21+
22+
constructor(range?: { start?: D, end?: D }) {
23+
this.start = range!.start || null;
24+
this.end = 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>) {}
18-
19-
destroy() {
20-
this._valueChangesSubject.complete();
21-
}
34+
constructor(public selection: S) {}
2235

23-
abstract add(date: D | null): void;
24-
abstract isComplete(): boolean;
25-
abstract isSame(other: MatDateSelectionModel<D>): boolean;
36+
abstract add(date: D): void;
2637
abstract isValid(): boolean;
27-
abstract overlaps(range: DateRange<D>): boolean;
38+
abstract isSame(other: MatDateSelectionModel<D>): boolean;
2839
}
2940

30-
export interface DateRange<D> {
31-
start: D | null;
32-
end: D | null;
33-
}
41+
42+
//export interface DateRange<D> {
43+
// start: D | null;
44+
// end: D | null;
45+
//}
3446

3547
/**
3648
* Concrete implementation of a MatDateSelectionModel that holds a single date.
3749
*/
3850
@Injectable()
39-
export class MatSingleDateSelectionModel<D> extends MatDateSelectionModel<D> {
40-
private _date: D | null = null;
41-
42-
constructor(adapter: DateAdapter<D>, date?: D | null) {
43-
super(adapter);
44-
this._date = date === undefined ? null : date;
45-
}
51+
export class MatSingleDateSelectionModel<D> extends MatDateSelectionModel<D, D> {
4652

47-
add(date: D | null) {
48-
this._date = date;
53+
add(date: D) {
54+
this.selection = date;
4955
this._valueChangesSubject.next();
5056
}
5157

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;
58+
isValid(): boolean {
59+
return this.selection != null;
5960
}
6061

61-
isComplete() { return this._date != null; }
62-
6362
isSame(other: MatDateSelectionModel<D>): boolean {
6463
return other instanceof MatSingleDateSelectionModel &&
65-
this.adapter.sameDate(other.asDate(), this._date);
66-
}
67-
68-
isValid(): boolean {
69-
return this._date != null && this.adapter.isDateInstance(this._date) &&
70-
this.adapter.isValid(this._date);
71-
}
72-
73-
asDate(): D | null {
74-
return this.isValid() ? this._date : null;
75-
}
76-
77-
setDate(date: D | null) {
78-
this._date = date;
79-
this._valueChangesSubject.next();
80-
}
81-
82-
/**
83-
* Determines if the single date is within a given date range. Retuns false if either dates of
84-
* the range is null or if the selection is undefined.
85-
*/
86-
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);
64+
this.selection === other.selection;
9065
}
9166
}
9267

@@ -95,96 +70,45 @@ export class MatSingleDateSelectionModel<D> extends MatDateSelectionModel<D> {
9570
* a start date and an end date.
9671
*/
9772
@Injectable()
98-
export class MatRangeDateSelectionModel<D> extends MatDateSelectionModel<D> {
99-
private _start: D | null = null;
100-
private _end: D | null = null;
101-
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;
106-
}
73+
export class MatRangeDateSelectionModel<D> extends
74+
MatDateSelectionModel<DateRange<D>, D> {
10775

10876
/**
10977
* Adds an additional date to the range. If no date is set thus far, it will set it to the
11078
* beginning. If the beginning is set, it will set it to the end.
11179
* If add is called on a complete selection, it will empty the selection and set it as the start.
11280
*/
113-
add(date: D | null): void {
114-
if (this._start == null) {
115-
this._start = date;
116-
} else if (this._end == null) {
117-
this._end = date;
81+
add(date: D): void {
82+
if (this.selection.start == null) {
83+
this.selection.start = date;
84+
} else if (this.selection.end == null) {
85+
this.selection.end = date;
11886
} else {
119-
this._start = date;
120-
this._end = null;
87+
this.selection.start = date;
88+
this.selection.end = null;
12189
}
12290

12391
this._valueChangesSubject.next();
12492
}
12593

12694
setRange(start: D | null, end: D | null) {
127-
this._start = start;
128-
this._end = end;
95+
this.selection.start = start;
96+
this.selection.end = end;
12997
}
13098

13199
isComplete(): boolean {
132-
return this._start != null && this._end != null;
133-
}
134-
135-
isSame(other: MatDateSelectionModel<D>): boolean {
136-
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);
140-
}
141-
return false;
100+
return this.selection.start != null && this.selection.end != null;
142101
}
143102

144103
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-
};
104+
return this.selection.start != null && this.selection.end != null;
154105
}
155106

156-
/**
157-
* Returns true if the given range and the selection overlap in any way. False if otherwise, that
158-
* includes incomplete selections or ranges.
159-
*/
160-
overlaps(range: DateRange<D>): boolean {
161-
if (!(this._start && this._end && range.start && range.end)) {
162-
return false;
107+
isSame(other: MatDateSelectionModel<D>): boolean {
108+
if (other instanceof MatRangeDateSelectionModel) {
109+
return this.selection.start === other.selection.start &&
110+
this.selection.end === other.selection.end;
163111
}
164-
165-
return (
166-
this._isBetween(range.start, this._start, this._end) ||
167-
this._isBetween(range.end, this._start, this._end) ||
168-
(
169-
this.adapter.compareDate(range.start, this._start) <= 0 &&
170-
this.adapter.compareDate(this._end, range.end) <= 0
171-
)
172-
);
173-
}
174-
175-
private _isBetween(value: D, from: D, to: D): boolean {
176-
return this.adapter.compareDate(from, value) <= 0 && this.adapter.compareDate(value, to) <= 0;
112+
return false;
177113
}
178114
}
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-
};

src/material/datepicker/datepicker-input.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,16 +129,18 @@ export class MatDatepickerInput<D> implements ControlValueAccessor, OnDestroy, V
129129

130130
/** The value of the input. */
131131
@Input()
132-
get value(): D | null { return this._selection.asDate(); }
132+
get value(): D | null { return this._selection.selection; }
133133
set value(value: D | null) {
134134
value = this._dateAdapter.deserialize(value);
135-
const oldDate = this._selection.asDate();
135+
const oldDate = this._selection.selection;
136136
const isDifferent = !this._dateAdapter.sameDate(oldDate, value);
137-
this._selection.setDate(value);
137+
if (value) {
138+
this._selection.add(value);
139+
}
138140

139141
this._lastValueValid = this._selection.isValid();
140142

141-
this._formatValue(this._selection.asDate());
143+
this._formatValue(this._selection.selection);
142144

143145
if (isDifferent) {
144146
this._valueChange.emit(this.value);
@@ -259,7 +261,7 @@ export class MatDatepickerInput<D> implements ControlValueAccessor, OnDestroy, V
259261
throw createMissingDateImplError('MAT_DATE_FORMATS');
260262
}
261263

262-
this._selection = new MatSingleDateSelectionModel(this._dateAdapter, null);
264+
this._selection = new MatSingleDateSelectionModel();
263265

264266
// Update the displayed date when the locale changes.
265267
this._localeSubscription = _dateAdapter.localeChanges.subscribe(() => {
@@ -334,8 +336,10 @@ export class MatDatepickerInput<D> implements ControlValueAccessor, OnDestroy, V
334336
this._lastValueValid = !date || this._dateAdapter.isValid(date);
335337
date = this._getValidDateOrNull(date);
336338

337-
if (!this._dateAdapter.sameDate(date, this._selection.asDate())) {
338-
this._selection.setDate(date);
339+
if (!this._dateAdapter.sameDate(date, this._selection.selection)) {
340+
if (date) {
341+
this._selection.add(date);
342+
}
339343
this._cvaOnChange(date);
340344
this._valueChange.emit(date);
341345
this.dateInput.emit(new MatDatepickerInputEvent(this, this._elementRef.nativeElement));

0 commit comments

Comments
 (0)