Skip to content

Commit 8063c26

Browse files
mmalerbaandrewseguin
authored andcommitted
fix(datepicker): make date range aria-live and fix active date logic (#11144)
* fix(datepicker): make date range aria-live and fix active date logic * switch to cdkAriaLive * fix tests
1 parent 2a51565 commit 8063c26

File tree

7 files changed

+71
-53
lines changed

7 files changed

+71
-53
lines changed

src/lib/datepicker/calendar-header.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
<div class="mat-calendar-header">
22
<div class="mat-calendar-controls">
33
<button mat-button type="button" class="mat-calendar-period-button"
4-
(click)="currentPeriodClicked()" [attr.aria-label]="periodButtonLabel">
4+
(click)="currentPeriodClicked()" [attr.aria-label]="periodButtonLabel"
5+
cdkAriaLive="polite">
56
{{periodButtonText}}
6-
<div class="mat-calendar-arrow" [class.mat-calendar-invert]="calendar.currentView != 'month'"></div>
7+
<div class="mat-calendar-arrow"
8+
[class.mat-calendar-invert]="calendar.currentView != 'month'"></div>
79
</button>
810

911
<div class="mat-calendar-spacer"></div>

src/lib/datepicker/calendar.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
<mat-year-view
1717
*ngSwitchCase="'year'"
18-
[activeDate]="activeDate"
18+
[(activeDate)]="activeDate"
1919
[selected]="selected"
2020
[dateFilter]="dateFilter"
2121
[maxDate]="maxDate"
@@ -26,7 +26,7 @@
2626

2727
<mat-multi-year-view
2828
*ngSwitchCase="'multi-year'"
29-
[activeDate]="activeDate"
29+
[(activeDate)]="activeDate"
3030
[selected]="selected"
3131
[dateFilter]="dateFilter"
3232
[maxDate]="maxDate"

src/lib/datepicker/month-view.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ export class MatMonthView<D> implements AfterContentInit {
177177
// navigation should skip over disabled dates, and if so, how to implement that efficiently.
178178

179179
const oldActiveDate = this._activeDate;
180-
181180
const isRtl = this._isRtl();
181+
182182
switch (event.keyCode) {
183183
case LEFT_ARROW:
184184
this.activeDate = this._dateAdapter.addCalendarDays(this._activeDate, isRtl ? 1 : -1);

src/lib/datepicker/multi-year-view.spec.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -118,103 +118,103 @@ describe('MatMultiYearView', () => {
118118
dispatchKeyboardEvent(calendarBodyEl, 'keydown', LEFT_ARROW);
119119
fixture.detectChanges();
120120

121-
expect(calendarInstance.multiYearView.activeDate).toEqual(new Date(2016, JAN, 1));
121+
expect(calendarInstance.date).toEqual(new Date(2016, JAN, 1));
122122

123123
dispatchKeyboardEvent(calendarBodyEl, 'keydown', LEFT_ARROW);
124124
fixture.detectChanges();
125125

126-
expect(calendarInstance.multiYearView.activeDate).toEqual(new Date(2015, JAN, 1));
126+
expect(calendarInstance.date).toEqual(new Date(2015, JAN, 1));
127127
});
128128

129129
it('should increment year on right arrow press', () => {
130130
dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW);
131131
fixture.detectChanges();
132132

133-
expect(calendarInstance.multiYearView.activeDate).toEqual(new Date(2018, JAN, 1));
133+
expect(calendarInstance.date).toEqual(new Date(2018, JAN, 1));
134134

135135
dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW);
136136
fixture.detectChanges();
137137

138-
expect(calendarInstance.multiYearView.activeDate).toEqual(new Date(2019, JAN, 1));
138+
expect(calendarInstance.date).toEqual(new Date(2019, JAN, 1));
139139
});
140140

141141
it('should go up a row on up arrow press', () => {
142142
dispatchKeyboardEvent(calendarBodyEl, 'keydown', UP_ARROW);
143143
fixture.detectChanges();
144144

145-
expect(calendarInstance.multiYearView.activeDate)
145+
expect(calendarInstance.date)
146146
.toEqual(new Date(2017 - yearsPerRow, JAN, 1));
147147

148148
dispatchKeyboardEvent(calendarBodyEl, 'keydown', UP_ARROW);
149149
fixture.detectChanges();
150150

151-
expect(calendarInstance.multiYearView.activeDate)
151+
expect(calendarInstance.date)
152152
.toEqual(new Date(2017 - yearsPerRow * 2, JAN, 1));
153153
});
154154

155155
it('should go down a row on down arrow press', () => {
156156
dispatchKeyboardEvent(calendarBodyEl, 'keydown', DOWN_ARROW);
157157
fixture.detectChanges();
158158

159-
expect(calendarInstance.multiYearView.activeDate)
159+
expect(calendarInstance.date)
160160
.toEqual(new Date(2017 + yearsPerRow, JAN, 1));
161161

162162
dispatchKeyboardEvent(calendarBodyEl, 'keydown', DOWN_ARROW);
163163
fixture.detectChanges();
164164

165-
expect(calendarInstance.multiYearView.activeDate)
165+
expect(calendarInstance.date)
166166
.toEqual(new Date(2017 + yearsPerRow * 2, JAN, 1));
167167
});
168168

169169
it('should go to first year in current range on home press', () => {
170170
dispatchKeyboardEvent(calendarBodyEl, 'keydown', HOME);
171171
fixture.detectChanges();
172172

173-
expect(calendarInstance.multiYearView.activeDate).toEqual(new Date(2016, JAN, 1));
173+
expect(calendarInstance.date).toEqual(new Date(2016, JAN, 1));
174174

175175
dispatchKeyboardEvent(calendarBodyEl, 'keydown', HOME);
176176
fixture.detectChanges();
177177

178-
expect(calendarInstance.multiYearView.activeDate).toEqual(new Date(2016, JAN, 1));
178+
expect(calendarInstance.date).toEqual(new Date(2016, JAN, 1));
179179
});
180180

181181
it('should go to last year in current range on end press', () => {
182182
dispatchKeyboardEvent(calendarBodyEl, 'keydown', END);
183183
fixture.detectChanges();
184184

185-
expect(calendarInstance.multiYearView.activeDate).toEqual(new Date(2039, JAN, 1));
185+
expect(calendarInstance.date).toEqual(new Date(2039, JAN, 1));
186186

187187
dispatchKeyboardEvent(calendarBodyEl, 'keydown', END);
188188
fixture.detectChanges();
189189

190-
expect(calendarInstance.multiYearView.activeDate).toEqual(new Date(2039, JAN, 1));
190+
expect(calendarInstance.date).toEqual(new Date(2039, JAN, 1));
191191
});
192192

193193
it('should go to same index in previous year range page up press', () => {
194194
dispatchKeyboardEvent(calendarBodyEl, 'keydown', PAGE_UP);
195195
fixture.detectChanges();
196196

197-
expect(calendarInstance.multiYearView.activeDate)
197+
expect(calendarInstance.date)
198198
.toEqual(new Date(2017 - yearsPerPage, JAN, 1));
199199

200200
dispatchKeyboardEvent(calendarBodyEl, 'keydown', PAGE_UP);
201201
fixture.detectChanges();
202202

203-
expect(calendarInstance.multiYearView.activeDate)
203+
expect(calendarInstance.date)
204204
.toEqual(new Date(2017 - yearsPerPage * 2, JAN, 1));
205205
});
206206

207207
it('should go to same index in next year range on page down press', () => {
208208
dispatchKeyboardEvent(calendarBodyEl, 'keydown', PAGE_DOWN);
209209
fixture.detectChanges();
210210

211-
expect(calendarInstance.multiYearView.activeDate)
211+
expect(calendarInstance.date)
212212
.toEqual(new Date(2017 + yearsPerPage, JAN, 1));
213213

214214
dispatchKeyboardEvent(calendarBodyEl, 'keydown', PAGE_DOWN);
215215
fixture.detectChanges();
216216

217-
expect(calendarInstance.multiYearView.activeDate)
217+
expect(calendarInstance.date)
218218
.toEqual(new Date(2017 + yearsPerPage * 2, JAN, 1));
219219
});
220220

@@ -246,7 +246,7 @@ describe('MatMultiYearView', () => {
246246

247247
@Component({
248248
template: `
249-
<mat-multi-year-view [activeDate]="date" [(selected)]="selected"
249+
<mat-multi-year-view [(activeDate)]="date" [(selected)]="selected"
250250
(yearSelected)="selectedYear=$event"></mat-multi-year-view>`
251251
})
252252
class StandardMultiYearView {

src/lib/datepicker/multi-year-view.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ export class MatMultiYearView<D> implements AfterContentInit {
101101
/** Emits the selected year. This doesn't imply a change on the selected date */
102102
@Output() readonly yearSelected: EventEmitter<D> = new EventEmitter<D>();
103103

104+
/** Emits when any date is activated. */
105+
@Output() readonly activeDateChange: EventEmitter<D> = new EventEmitter<D>();
106+
104107
/** The body of calendar table */
105108
@ViewChild(MatCalendarBody) _matCalendarBody: MatCalendarBody;
106109

@@ -159,6 +162,7 @@ export class MatMultiYearView<D> implements AfterContentInit {
159162
// disabled ones from being selected. This may not be ideal, we should look into whether
160163
// navigation should skip over disabled dates, and if so, how to implement that efficiently.
161164

165+
const oldActiveDate = this._activeDate;
162166
const isRtl = this._isRtl();
163167

164168
switch (event.keyCode) {
@@ -200,6 +204,10 @@ export class MatMultiYearView<D> implements AfterContentInit {
200204
return;
201205
}
202206

207+
if (this._dateAdapter.compareDate(oldActiveDate, this.activeDate)) {
208+
this.activeDateChange.emit(this.activeDate);
209+
}
210+
203211
this._focusActiveCell();
204212
// Prevent unexpected default actions such as form submission.
205213
event.preventDefault();

src/lib/datepicker/year-view.spec.ts

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,12 @@ describe('MatYearView', () => {
147147
dispatchKeyboardEvent(calendarBodyEl, 'keydown', LEFT_ARROW);
148148
fixture.detectChanges();
149149

150-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2016, DEC, 5));
150+
expect(calendarInstance.date).toEqual(new Date(2016, DEC, 5));
151151

152152
dispatchKeyboardEvent(calendarBodyEl, 'keydown', LEFT_ARROW);
153153
fixture.detectChanges();
154154

155-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2016, NOV, 5));
155+
expect(calendarInstance.date).toEqual(new Date(2016, NOV, 5));
156156
});
157157

158158
it('should increment month on left arrow press in rtl', () => {
@@ -161,24 +161,24 @@ describe('MatYearView', () => {
161161
dispatchKeyboardEvent(calendarBodyEl, 'keydown', LEFT_ARROW);
162162
fixture.detectChanges();
163163

164-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2017, FEB, 5));
164+
expect(calendarInstance.date).toEqual(new Date(2017, FEB, 5));
165165

166166
dispatchKeyboardEvent(calendarBodyEl, 'keydown', LEFT_ARROW);
167167
fixture.detectChanges();
168168

169-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2017, MAR, 5));
169+
expect(calendarInstance.date).toEqual(new Date(2017, MAR, 5));
170170
});
171171

172172
it('should increment month on right arrow press', () => {
173173
dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW);
174174
fixture.detectChanges();
175175

176-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2017, FEB, 5));
176+
expect(calendarInstance.date).toEqual(new Date(2017, FEB, 5));
177177

178178
dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW);
179179
fixture.detectChanges();
180180

181-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2017, MAR, 5));
181+
expect(calendarInstance.date).toEqual(new Date(2017, MAR, 5));
182182
});
183183

184184
it('should decrement month on right arrow press in rtl', () => {
@@ -187,118 +187,118 @@ describe('MatYearView', () => {
187187
dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW);
188188
fixture.detectChanges();
189189

190-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2016, DEC, 5));
190+
expect(calendarInstance.date).toEqual(new Date(2016, DEC, 5));
191191

192192
dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW);
193193
fixture.detectChanges();
194194

195-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2016, NOV, 5));
195+
expect(calendarInstance.date).toEqual(new Date(2016, NOV, 5));
196196
});
197197

198198
it('should go up a row on up arrow press', () => {
199199
dispatchKeyboardEvent(calendarBodyEl, 'keydown', UP_ARROW);
200200
fixture.detectChanges();
201201

202-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2016, SEP, 5));
202+
expect(calendarInstance.date).toEqual(new Date(2016, SEP, 5));
203203

204-
calendarInstance.yearView.activeDate = new Date(2017, JUL, 1);
204+
calendarInstance.date = new Date(2017, JUL, 1);
205205
fixture.detectChanges();
206206

207207
dispatchKeyboardEvent(calendarBodyEl, 'keydown', UP_ARROW);
208208
fixture.detectChanges();
209209

210-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2017, MAR, 1));
210+
expect(calendarInstance.date).toEqual(new Date(2017, MAR, 1));
211211

212-
calendarInstance.yearView.activeDate = new Date(2017, DEC, 10);
212+
calendarInstance.date = new Date(2017, DEC, 10);
213213
fixture.detectChanges();
214214

215215
dispatchKeyboardEvent(calendarBodyEl, 'keydown', UP_ARROW);
216216
fixture.detectChanges();
217217

218-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2017, AUG, 10));
218+
expect(calendarInstance.date).toEqual(new Date(2017, AUG, 10));
219219
});
220220

221221
it('should go down a row on down arrow press', () => {
222222
dispatchKeyboardEvent(calendarBodyEl, 'keydown', DOWN_ARROW);
223223
fixture.detectChanges();
224224

225-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2017, MAY, 5));
225+
expect(calendarInstance.date).toEqual(new Date(2017, MAY, 5));
226226

227-
calendarInstance.yearView.activeDate = new Date(2017, JUN, 1);
227+
calendarInstance.date = new Date(2017, JUN, 1);
228228
fixture.detectChanges();
229229

230230
dispatchKeyboardEvent(calendarBodyEl, 'keydown', DOWN_ARROW);
231231
fixture.detectChanges();
232232

233-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2017, OCT, 1));
233+
expect(calendarInstance.date).toEqual(new Date(2017, OCT, 1));
234234

235-
calendarInstance.yearView.activeDate = new Date(2017, SEP, 30);
235+
calendarInstance.date = new Date(2017, SEP, 30);
236236
fixture.detectChanges();
237237

238238
dispatchKeyboardEvent(calendarBodyEl, 'keydown', DOWN_ARROW);
239239
fixture.detectChanges();
240240

241-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2018, JAN, 30));
241+
expect(calendarInstance.date).toEqual(new Date(2018, JAN, 30));
242242
});
243243

244244
it('should go to first month of the year on home press', () => {
245-
calendarInstance.yearView.activeDate = new Date(2017, SEP, 30);
245+
calendarInstance.date = new Date(2017, SEP, 30);
246246
fixture.detectChanges();
247247

248248
dispatchKeyboardEvent(calendarBodyEl, 'keydown', HOME);
249249
fixture.detectChanges();
250250

251-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2017, JAN, 30));
251+
expect(calendarInstance.date).toEqual(new Date(2017, JAN, 30));
252252

253253
dispatchKeyboardEvent(calendarBodyEl, 'keydown', HOME);
254254
fixture.detectChanges();
255255

256-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2017, JAN, 30));
256+
expect(calendarInstance.date).toEqual(new Date(2017, JAN, 30));
257257
});
258258

259259
it('should go to last month of the year on end press', () => {
260-
calendarInstance.yearView.activeDate = new Date(2017, OCT, 31);
260+
calendarInstance.date = new Date(2017, OCT, 31);
261261
fixture.detectChanges();
262262

263263
dispatchKeyboardEvent(calendarBodyEl, 'keydown', END);
264264
fixture.detectChanges();
265265

266-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2017, DEC, 31));
266+
expect(calendarInstance.date).toEqual(new Date(2017, DEC, 31));
267267

268268
dispatchKeyboardEvent(calendarBodyEl, 'keydown', END);
269269
fixture.detectChanges();
270270

271-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2017, DEC, 31));
271+
expect(calendarInstance.date).toEqual(new Date(2017, DEC, 31));
272272
});
273273

274274
it('should go back one year on page up press', () => {
275-
calendarInstance.yearView.activeDate = new Date(2016, FEB, 29);
275+
calendarInstance.date = new Date(2016, FEB, 29);
276276
fixture.detectChanges();
277277

278278
dispatchKeyboardEvent(calendarBodyEl, 'keydown', PAGE_UP);
279279
fixture.detectChanges();
280280

281-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2015, FEB, 28));
281+
expect(calendarInstance.date).toEqual(new Date(2015, FEB, 28));
282282

283283
dispatchKeyboardEvent(calendarBodyEl, 'keydown', PAGE_UP);
284284
fixture.detectChanges();
285285

286-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2014, FEB, 28));
286+
expect(calendarInstance.date).toEqual(new Date(2014, FEB, 28));
287287
});
288288

289289
it('should go forward one year on page down press', () => {
290-
calendarInstance.yearView.activeDate = new Date(2016, FEB, 29);
290+
calendarInstance.date = new Date(2016, FEB, 29);
291291
fixture.detectChanges();
292292

293293
dispatchKeyboardEvent(calendarBodyEl, 'keydown', PAGE_DOWN);
294294
fixture.detectChanges();
295295

296-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2017, FEB, 28));
296+
expect(calendarInstance.date).toEqual(new Date(2017, FEB, 28));
297297

298298
dispatchKeyboardEvent(calendarBodyEl, 'keydown', PAGE_DOWN);
299299
fixture.detectChanges();
300300

301-
expect(calendarInstance.yearView.activeDate).toEqual(new Date(2018, FEB, 28));
301+
expect(calendarInstance.date).toEqual(new Date(2018, FEB, 28));
302302
});
303303
});
304304
});
@@ -327,7 +327,7 @@ describe('MatYearView', () => {
327327

328328
@Component({
329329
template: `
330-
<mat-year-view [activeDate]="date" [(selected)]="selected"
330+
<mat-year-view [(activeDate)]="date" [(selected)]="selected"
331331
(monthSelected)="selectedMonth=$event"></mat-year-view>`
332332
})
333333
class StandardYearView {

0 commit comments

Comments
 (0)