Skip to content

Commit 4cc8003

Browse files
roboshoesmmalerba
authored andcommitted
Adds an abstract date selection model (#13033)
This PR also includes a single date implementation of the selection model and the range implementation.
1 parent 5c8e0cb commit 4cc8003

File tree

2 files changed

+157
-0
lines changed

2 files changed

+157
-0
lines changed
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {DateAdapter} from '@angular/material/core';
10+
11+
export abstract class MatDateSelection<D> {
12+
constructor(protected readonly adapter: DateAdapter<D>) {}
13+
14+
abstract add(date: D): void;
15+
abstract clone(): MatDateSelection<D>;
16+
abstract getFirstSelectedDate(): D|null;
17+
abstract getLastSelectedDate(): D|null;
18+
abstract isComplete(): boolean;
19+
abstract isSame(other: MatDateSelection<D>): boolean;
20+
abstract isValid(): boolean;
21+
}
22+
23+
export interface DateRange<D> {
24+
start: D | null;
25+
end: D | null;
26+
}
27+
28+
/**
29+
* Concrete implementation of a MatDateSelection that holds a single date.
30+
*/
31+
export class MatSingleDateSelection<D> extends MatDateSelection<D> {
32+
private date: D | null = null;
33+
34+
constructor(adapter: DateAdapter<D>, date?: D | null) {
35+
super(adapter);
36+
37+
if (date) {
38+
this.date = date;
39+
}
40+
}
41+
42+
add(date: D) {
43+
this.date = date;
44+
}
45+
46+
clone(): MatDateSelection<D> {
47+
const copy = new MatSingleDateSelection<D>(this.adapter);
48+
49+
if (this.date) {
50+
copy.add(this.adapter.clone(this.date));
51+
}
52+
53+
return copy as MatDateSelection<D>;
54+
}
55+
56+
getFirstSelectedDate() { return this.date; }
57+
58+
getLastSelectedDate() { return this.date; }
59+
60+
isComplete() { return !!this.date; }
61+
62+
isSame(other: MatDateSelection<D>): boolean {
63+
return other instanceof MatSingleDateSelection &&
64+
this.adapter.sameDate(other.getFirstSelectedDate(), this.getFirstSelectedDate());
65+
}
66+
67+
isValid(): boolean {
68+
return !!(this.date && this.adapter.isValid(this.date));
69+
}
70+
71+
asDate(): D | null {
72+
return this.date;
73+
}
74+
}
75+
76+
/**
77+
* Concrete implementation of a MatDateSelection that holds a date range, represented by
78+
* a start date and an end date.
79+
*/
80+
export class MatRangeDateSelection<D> extends MatDateSelection<D> {
81+
private start: D | null = null;
82+
private end: D | null = null;
83+
84+
constructor(adapter: DateAdapter<D>, start?: D | null, end?: D | null) {
85+
super(adapter);
86+
87+
if (start) {
88+
this.start = start;
89+
}
90+
91+
if (end) {
92+
this.end = end;
93+
}
94+
}
95+
96+
/**
97+
* Adds an additional date to the range. If no date is set thus far, it will set it to the
98+
* beginning. If the beginning is set, it will set it to the end.
99+
* If add is called on a complete selection, it will empty the selection and set it as the start.
100+
*/
101+
add(date: D): void {
102+
if (!this.start) {
103+
this.start = date;
104+
} else if (!this.end) {
105+
this.end = date;
106+
} else {
107+
this.start = date;
108+
this.end = null;
109+
}
110+
}
111+
112+
113+
clone(): MatDateSelection<D> {
114+
const copy = new MatRangeDateSelection<D>(this.adapter);
115+
116+
if (this.start) {
117+
copy.setFirstSelectedDate(this.adapter.clone(this.start));
118+
}
119+
120+
if (this.end) {
121+
copy.setLastSelectedDate(this.adapter.clone(this.end));
122+
}
123+
124+
return copy as MatDateSelection<D>;
125+
}
126+
127+
getFirstSelectedDate() { return this.start; }
128+
129+
getLastSelectedDate() { return this.end; }
130+
131+
setFirstSelectedDate(value: D | null) { this.start = value; }
132+
133+
setLastSelectedDate(value: D | null) { this.end = value; }
134+
135+
isComplete(): boolean {
136+
return !!(this.start && this.end);
137+
}
138+
139+
isSame(other: MatDateSelection<D>): boolean {
140+
return other instanceof MatRangeDateSelection &&
141+
this.adapter.sameDate(this.getFirstSelectedDate(), other.getFirstSelectedDate()) &&
142+
this.adapter.sameDate(this.getLastSelectedDate(), other.getLastSelectedDate());
143+
}
144+
145+
isValid(): boolean {
146+
return !!(this.start && this.end &&
147+
this.adapter.isValid(this.start!) && this.adapter.isValid(this.end!));
148+
}
149+
150+
asRange(): DateRange<D> {
151+
return {
152+
start: this.start,
153+
end: this.end,
154+
};
155+
}
156+
}

src/lib/core/datetime/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export * from './date-adapter';
1717
export * from './date-formats';
1818
export * from './native-date-adapter';
1919
export * from './native-date-formats';
20+
export * from './date-selection';
2021

2122

2223
@NgModule({

0 commit comments

Comments
 (0)