Skip to content

Commit 9150ac0

Browse files
committed
share func feat(datepicker): align multi-year-view based on minDate and maxDate
1 parent 20c6256 commit 9150ac0

File tree

2 files changed

+54
-75
lines changed

2 files changed

+54
-75
lines changed

src/material/datepicker/calendar.ts

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ import {Subject, Subscription} from 'rxjs';
3030
import {createMissingDateImplError} from './datepicker-errors';
3131
import {MatDatepickerIntl} from './datepicker-intl';
3232
import {MatMonthView} from './month-view';
33-
import {MatMultiYearView, yearsPerPage, euclideanModulo} from './multi-year-view';
33+
import {MatMultiYearView,
34+
yearsPerPage,
35+
getActiveOffset,
36+
isSameMultiYearView} from './multi-year-view';
3437
import {MatYearView} from './year-view';
3538
import {MatCalendarCellCssClasses} from './calendar-body';
3639

@@ -74,7 +77,8 @@ export class MatCalendarHeader<D> {
7477
// *actual* first rendered year in the multi-year view, and the last year is
7578
// just yearsPerPage - 1 away.
7679
const activeYear = this._dateAdapter.getYear(this.calendar.activeDate);
77-
const minYearOfPage = activeYear - this._getActiveOffset();
80+
const minYearOfPage = activeYear - getActiveOffset(
81+
this._dateAdapter, this.calendar.activeDate, this.calendar.minDate, this.calendar.maxDate);
7882
const maxYearOfPage = minYearOfPage + yearsPerPage - 1;
7983
return `${minYearOfPage} \u2013 ${maxYearOfPage}`;
8084
}
@@ -151,40 +155,8 @@ export class MatCalendarHeader<D> {
151155
return this._dateAdapter.getYear(date1) == this._dateAdapter.getYear(date2);
152156
}
153157
// Otherwise we are in 'multi-year' view.
154-
return this._isSameMultiYearView(date1, date2);
155-
}
156-
157-
private _isSameMultiYearView(date1: D, date2: D): boolean {
158-
const year1 = this._dateAdapter.getYear(date1);
159-
const year2 = this._dateAdapter.getYear(date2);
160-
const startingYear = this._getStartingYear();
161-
return Math.floor((year1 - startingYear) / yearsPerPage) ===
162-
Math.floor((year2 - startingYear) / yearsPerPage);
163-
}
164-
165-
/**
166-
* When the multi-year view is first opened, the active year will be in view.
167-
* So we compute how many years are between the active year and the *slot* where our
168-
* "startingYear" will render when paged into view.
169-
*/
170-
private _getActiveOffset(): number {
171-
const activeYear = this._dateAdapter.getYear(this.calendar.activeDate);
172-
return euclideanModulo((activeYear - this._getStartingYear()), yearsPerPage);
173-
}
174-
175-
/**
176-
* We pick a "starting" year such that either the maximum year would be at the end
177-
* or the minimum year would be at the beginning of a page.
178-
*/
179-
private _getStartingYear(): number {
180-
let startingYear = 0;
181-
if (this.calendar.maxDate) {
182-
const maxYear = this._dateAdapter.getYear(this.calendar.maxDate);
183-
startingYear = maxYear - yearsPerPage + 1;
184-
} else if (this.calendar.minDate) {
185-
startingYear = this._dateAdapter.getYear(this.calendar.minDate);
186-
}
187-
return startingYear;
158+
return isSameMultiYearView(
159+
this._dateAdapter, date1, date2, this.calendar.minDate, this.calendar.maxDate);
188160
}
189161
}
190162

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

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ export class MatMultiYearView<D> implements AfterContentInit {
6161
this._getValidDateOrNull(this._dateAdapter.deserialize(value)) || this._dateAdapter.today();
6262
this._activeDate = this._dateAdapter.clampDate(validDate, this.minDate, this.maxDate);
6363

64-
if (!this._isSameMultiYearView(oldActiveDate, this._activeDate)) {
64+
if (!isSameMultiYearView(
65+
this._dateAdapter, oldActiveDate, this._activeDate, this.minDate, this.maxDate)) {
6566
this._init();
6667
}
6768
}
@@ -141,7 +142,8 @@ export class MatMultiYearView<D> implements AfterContentInit {
141142
// The offset from the active year to the "slot" for the starting year is the
142143
// *actual* first rendered year in the multi-year view.
143144
const activeYear = this._dateAdapter.getYear(this._activeDate);
144-
const minYearOfPage = activeYear - this._getActiveOffset();
145+
const minYearOfPage = activeYear - getActiveOffset(
146+
this._dateAdapter, this.activeDate, this.minDate, this.maxDate);
145147

146148
this._years = [];
147149
for (let i = 0, row: number[] = []; i < yearsPerPage; i++) {
@@ -184,11 +186,12 @@ export class MatMultiYearView<D> implements AfterContentInit {
184186
break;
185187
case HOME:
186188
this.activeDate = this._dateAdapter.addCalendarYears(this._activeDate,
187-
-this._getActiveOffset());
189+
-getActiveOffset(this._dateAdapter, this.activeDate, this.minDate, this.maxDate));
188190
break;
189191
case END:
190192
this.activeDate = this._dateAdapter.addCalendarYears(this._activeDate,
191-
yearsPerPage - this._getActiveOffset() - 1);
193+
yearsPerPage - getActiveOffset(
194+
this._dateAdapter, this.activeDate, this.minDate, this.maxDate) - 1);
192195
break;
193196
case PAGE_UP:
194197
this.activeDate =
@@ -218,47 +221,14 @@ export class MatMultiYearView<D> implements AfterContentInit {
218221
}
219222

220223
_getActiveCell(): number {
221-
return this._getActiveOffset();
224+
return getActiveOffset(this._dateAdapter, this.activeDate, this.minDate, this.maxDate);
222225
}
223226

224227
/** Focuses the active cell after the microtask queue is empty. */
225228
_focusActiveCell() {
226229
this._matCalendarBody._focusActiveCell();
227230
}
228231

229-
private _isSameMultiYearView(date1: D, date2: D): boolean {
230-
const year1 = this._dateAdapter.getYear(date1);
231-
const year2 = this._dateAdapter.getYear(date2);
232-
const startingYear = this._getStartingYear();
233-
return Math.floor((year1 - startingYear) / yearsPerPage) ===
234-
Math.floor((year2 - startingYear) / yearsPerPage);
235-
}
236-
237-
/**
238-
* When the multi-year view is first opened, the active year will be in view.
239-
* So we compute how many years are between the active year and the *slot* where our
240-
* "startingYear" will render when paged into view.
241-
*/
242-
private _getActiveOffset(): number {
243-
const activeYear = this._dateAdapter.getYear(this.activeDate);
244-
return euclideanModulo((activeYear - this._getStartingYear()), yearsPerPage);
245-
}
246-
247-
/**
248-
* We pick a "starting" year such that either the maximum year would be at the end
249-
* or the minimum year would be at the beginning of a page.
250-
*/
251-
private _getStartingYear(): number {
252-
let startingYear = 0;
253-
if (this.maxDate) {
254-
const maxYear = this._dateAdapter.getYear(this.maxDate);
255-
startingYear = maxYear - yearsPerPage + 1;
256-
} else if (this.minDate) {
257-
startingYear = this._dateAdapter.getYear(this.minDate);
258-
}
259-
return startingYear;
260-
}
261-
262232
/** Creates an MatCalendarCell for the given year. */
263233
private _createCellForYear(year: number) {
264234
let yearName = this._dateAdapter.getYearName(this._dateAdapter.createDate(year, 0, 1));
@@ -306,7 +276,44 @@ export class MatMultiYearView<D> implements AfterContentInit {
306276
}
307277
}
308278

279+
export function isSameMultiYearView<D>(
280+
dateAdapter: DateAdapter<D>, date1: D, date2: D, minDate: D | null, maxDate: D | null): boolean {
281+
const year1 = dateAdapter.getYear(date1);
282+
const year2 = dateAdapter.getYear(date2);
283+
const startingYear = getStartingYear(dateAdapter, minDate, maxDate);
284+
return Math.floor((year1 - startingYear) / yearsPerPage) ===
285+
Math.floor((year2 - startingYear) / yearsPerPage);
286+
}
287+
288+
/**
289+
* When the multi-year view is first opened, the active year will be in view.
290+
* So we compute how many years are between the active year and the *slot* where our
291+
* "startingYear" will render when paged into view.
292+
*/
293+
export function getActiveOffset<D>(
294+
dateAdapter: DateAdapter<D>, activeDate: D, minDate: D | null, maxDate: D | null): number {
295+
const activeYear = dateAdapter.getYear(activeDate);
296+
return euclideanModulo((activeYear - getStartingYear(dateAdapter, minDate, maxDate)),
297+
yearsPerPage);
298+
}
299+
300+
/**
301+
* We pick a "starting" year such that either the maximum year would be at the end
302+
* or the minimum year would be at the beginning of a page.
303+
*/
304+
function getStartingYear<D>(
305+
dateAdapter: DateAdapter<D>, minDate: D | null, maxDate: D | null): number {
306+
let startingYear = 0;
307+
if (maxDate) {
308+
const maxYear = dateAdapter.getYear(maxDate);
309+
startingYear = maxYear - yearsPerPage + 1;
310+
} else if (minDate) {
311+
startingYear = dateAdapter.getYear(minDate);
312+
}
313+
return startingYear;
314+
}
315+
309316
/** Gets remainder that is non-negative, even if first number is negative */
310-
export function euclideanModulo (a: number, b: number): number {
317+
function euclideanModulo (a: number, b: number): number {
311318
return (a % b + b) % b;
312319
}

0 commit comments

Comments
 (0)