Skip to content
This repository was archived by the owner on May 20, 2023. It is now read-only.

Commit 85cf0a3

Browse files
cpellingnshahan
authored andcommitted
material-date-range-picker: Add an option to disable maintaining the length of the date range when clicking on the calendar to move the start date.
By default, the previous behavior is kept. If this option is set to false, moving the start date after the end date will collapse the range into a single day (the one you just clicked). This mirrors the existing behavior (shared by both configurations) where moving the end date after the start date collapses the range into a single day. The following related behaviors are unchanged, regardless of configuration: * Changing the end date already doesn't change the start date. * Clicking-and-dragging the range endpoints always moves them independently. Dragging one endpoint past the other endpoint does not collapse the range, but rather allows the old start date to become the new end date (or vice versa). Also update the demo to showcase some of the newer preset types (Quarter and Broadcast month). PiperOrigin-RevId: 208853492
1 parent bee534c commit 85cf0a3

12 files changed

+120
-29
lines changed

lib/material_datepicker/calendar.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'package:collection/collection.dart';
66
import 'package:intl/intl.dart';
7+
import 'package:meta/meta.dart';
78
import 'package:angular_components/model/date/date.dart';
89

910
part '../src/material_datepicker/calendar/day.dart';
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// Global configuration options for datepicker components.
6+
class DatepickerConfig {
7+
/// For date range selection, whether clicking to move the start date should
8+
/// also move the end date (preserving the length of the selected range).
9+
///
10+
/// Defaults to true. No effect on single-date calendars.
11+
final bool movingStartMaintainsLength;
12+
13+
DatepickerConfig({this.movingStartMaintainsLength = true});
14+
}

lib/material_datepicker/date_range_editor.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,13 @@ class DateRangeEditorComponent implements OnInit, AfterViewInit, Focusable {
127127

128128
bool _compact = false;
129129

130+
/// For date range selection, whether clicking to move the start date should
131+
/// also move the end date (preserving the length of the selected range).
132+
///
133+
/// Defaults to true, unless an enclosing component has a different default.
134+
@Input()
135+
bool movingStartMaintainsLength = true;
136+
130137
/// Whether or not this editor includes a section to input 'N days up to
131138
/// today' and 'N days up to yesterday' ranges.
132139
///

lib/material_datepicker/date_range_editor.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@
157157
[maxDate]="maxDate"
158158
[allowHighlightUpdates]="allowHighlightUpdates"
159159
[compact]="compact"
160+
[movingStartMaintainsLength]="movingStartMaintainsLength"
160161
(visibleMonth)="onVisibleMonthChange"
161162
mode="date-range">
162163
</material-calendar-picker>

lib/material_datepicker/material_calendar_picker.dart

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,23 @@ class MaterialCalendarPickerComponent
245245
bool get compact => _compact;
246246
bool _compact = false;
247247

248+
/// For date range selection, whether clicking to move the start date should
249+
/// also move the end date (preserving the length of the selected range).
250+
///
251+
/// Defaults to true, unless an enclosing component has a different default.
252+
@Input()
253+
set movingStartMaintainsLength(bool value) {
254+
_movingStartMaintainsLength = value;
255+
256+
// Must recreate the input listener when this changes. If it wasn't already
257+
// created, we must be executing before [ngOnInit], so defer to later.
258+
if (_inputListener != null) {
259+
_initInputListener();
260+
}
261+
}
262+
263+
bool _movingStartMaintainsLength = true;
264+
248265
/// What sort of interaction this calendar supports.
249266
CalendarSelectionMode get mode => _mode;
250267
CalendarSelectionMode _mode = CalendarSelectionMode.NONE;
@@ -575,7 +592,8 @@ class MaterialCalendarPickerComponent
575592
// Simulate applying the selection to get the [CalendarSelection] that
576593
// would be created if it were actually applied. Since [CalendarState] is
577594
// immutable, this doesn't modify any state.
578-
var previewState = state.confirmPreview();
595+
var previewState = state.confirmPreview(
596+
movingStartMaintainsLength: _movingStartMaintainsLength);
579597
var previewRange = previewState
580598
.selection(previewState.currentSelection)
581599
.clamp(min: minDate, max: maxDate);
@@ -725,11 +743,16 @@ class MaterialCalendarPickerComponent
725743
void ngOnInit() {
726744
_calendarStream = _model.stream.listen(_onCalendarChange);
727745

746+
_initInputListener();
747+
}
748+
749+
void _initInputListener() {
728750
if (_mode == CalendarSelectionMode.SINGLE_DATE) {
729751
_inputListener = CalendarListener.singleDate(_model);
730752
}
731753
if (_mode == CalendarSelectionMode.DATE_RANGE) {
732-
_inputListener = CalendarListener.dateRange(_model);
754+
_inputListener = CalendarListener.dateRange(_model,
755+
movingStartMaintainsLength: _movingStartMaintainsLength);
733756
}
734757
}
735758

lib/material_datepicker/material_date_grid_base.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ abstract class MaterialDateGridBase
151151
_inputListener = CalendarListener.singleDate(model);
152152
}
153153
if (mode == CalendarSelectionMode.DATE_RANGE) {
154-
_inputListener = CalendarListener.dateRange(model);
154+
_inputListener =
155+
CalendarListener.dateRange(model, movingStartMaintainsLength: true);
155156
}
156157
_disposer.addDisposable(_inputListener);
157158

lib/material_datepicker/material_date_range_picker.dart

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import 'package:angular_components/laminate/popup/popup.dart';
1919
import 'package:angular_components/material_button/material_button.dart';
2020
import 'package:angular_components/material_datepicker/comparison.dart';
2121
import 'package:angular_components/material_datepicker/comparison_option.dart';
22+
import 'package:angular_components/material_datepicker/config.dart';
2223
import 'package:angular_components/material_datepicker/date_range_editor.dart';
2324
import 'package:angular_components/material_datepicker/module.dart';
2425
import 'package:angular_components/material_datepicker/next_prev_buttons.dart';
@@ -206,6 +207,20 @@ class MaterialDateRangePickerComponent extends KeyboardHandlerMixin
206207

207208
bool _compact = !window.matchMedia("(pointer: coarse)").matches;
208209

210+
/// For date range selection, whether clicking to move the start date should
211+
/// also move the end date (preserving the length of the selected range).
212+
///
213+
/// Defaults to [DatepickerConfig.movingStartMaintainsLength] if a
214+
/// [DatepickerConfig] object is provided through dependency injection.
215+
@Input()
216+
set movingStartMaintainsLength(bool value) {
217+
_movingStartMaintainsLength = value;
218+
}
219+
220+
get movingStartMaintainsLength =>
221+
_movingStartMaintainsLength ?? _config.movingStartMaintainsLength;
222+
bool _movingStartMaintainsLength;
223+
209224
/// The label for the 'Apply' button. Set this variable only if you want a
210225
/// different label other than 'Apply'. If set, the input label should be
211226
/// internationalized.
@@ -344,6 +359,7 @@ class MaterialDateRangePickerComponent extends KeyboardHandlerMixin
344359

345360
final DomService _domService;
346361
final NgZone _ngZone;
362+
final DatepickerConfig _config;
347363

348364
/// CSS classes from the root element, passed to the popup to allow scoping of
349365
/// mixins.
@@ -354,11 +370,13 @@ class MaterialDateRangePickerComponent extends KeyboardHandlerMixin
354370
MaterialDateRangePickerComponent(
355371
@Optional() @Inject(datepickerClock) Clock clock,
356372
Clock legacyClock,
373+
@Optional() DatepickerConfig config,
357374
@Attribute('popupClass') String popupClass,
358375
HtmlElement element,
359376
this._domService,
360377
this._ngZone)
361-
: popupClassName = constructEncapsulatedCss(popupClass, element.classes) {
378+
: _config = config ?? DatepickerConfig(),
379+
popupClassName = constructEncapsulatedCss(popupClass, element.classes) {
362380
// TODO(google): Migrate to use only datepickerClock
363381
clock ??= legacyClock;
364382

lib/material_datepicker/material_date_range_picker.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
[maxDate]="maxDate"
6161
[allowHighlightUpdates]="allowHighlightUpdates"
6262
[compact]="compact"
63+
[movingStartMaintainsLength]="movingStartMaintainsLength"
6364
[calendarCreated]="isCalendarCreated"
6465
[supportsCustomRange]="supportsCustomRange"
6566
[relativeDaysToToday]="relativeDaysToToday"

lib/material_datepicker/material_month_picker.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,10 @@ class MaterialMonthPickerComponent
274274
if (_mode == CalendarSelectionMode.SINGLE_DATE) {
275275
_inputListener = CalendarListener.singleDate(_model);
276276
} else if (_mode == CalendarSelectionMode.DATE_RANGE) {
277-
_inputListener = CalendarListener.dateRange(_model);
277+
// TODO(google): Add support for movingStartMaintainsLength==false if
278+
// we see use cases for month range picking.
279+
_inputListener =
280+
CalendarListener.dateRange(_model, movingStartMaintainsLength: true);
278281
}
279282
}
280283

lib/material_datepicker/range.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -883,8 +883,6 @@ DatepickerDateRange lastQuarter(Clock clock) =>
883883
DatepickerDateRange allTime = DatepickerDateRange(_allTimeMsg, null, null,
884884
isPredefined: true, isAllTime: true);
885885

886-
// TODO(google): AWN no longer uses thisYear and lastYear. Check cross-team
887-
// to see if we should remove those entries from commonRanges as well.
888886
List<DatepickerDateRange> commonRanges(Clock clock) => [
889887
today(clock),
890888
yesterday(clock),

0 commit comments

Comments
 (0)