diff --git a/src/material/datepicker/date-range-input-parts.ts b/src/material/datepicker/date-range-input-parts.ts index 6d30b24e88e3..1d21399317fe 100644 --- a/src/material/datepicker/date-range-input-parts.ts +++ b/src/material/datepicker/date-range-input-parts.ts @@ -40,7 +40,7 @@ import { import {BooleanInput} from '@angular/cdk/coercion'; import {BACKSPACE} from '@angular/cdk/keycodes'; import {MatDatepickerInputBase, DateFilterFn} from './datepicker-input-base'; -import {DateRange, MatDateSelectionModel} from './date-selection-model'; +import {DateRange} from './date-selection-model'; /** Parent component that should be wrapped around `MatStartDate` and `MatEndDate`. */ export interface MatDateRangeInputParent { @@ -165,15 +165,6 @@ abstract class MatDateRangeInputPartBase protected _parentDisabled() { return this._rangeInput._groupDisabled; } - - _registerModel(model: MatDateSelectionModel, D>) { - // The very first time the range inputs write their values, they don't know about the value - // of the opposite input. When this is combined with the fact that `NgModel` defers writing - // its value with a `Promise.resolve`, we can get into a situation where the first input - // resets the value of the second. We work around it by deferring the registration of - // the model, allowing the input enough time to assign the initial value. - Promise.resolve().then(() => super._registerModel(model)); - } } const _MatDateRangeInputBase: @@ -242,6 +233,7 @@ export class MatStartDate extends _MatDateRangeInputBase implements CanUpd if (this._model) { const range = new DateRange(value, this._model.selection.end); this._model.updateSelection(range, this); + this._cvaOnChange(value); } } @@ -323,11 +315,12 @@ export class MatEndDate extends _MatDateRangeInputBase implements CanUpdat if (this._model) { const range = new DateRange(this._model.selection.start, value); this._model.updateSelection(range, this); + this._cvaOnChange(value); } } _onKeydown(event: KeyboardEvent) { - // If the user is pressing backspace on an empty end input, focus focus back to the start. + // If the user is pressing backspace on an empty end input, move focus back to the start. if (event.keyCode === BACKSPACE && !this._elementRef.nativeElement.value) { this._rangeInput._startInput.focus(); } diff --git a/src/material/datepicker/date-range-input.spec.ts b/src/material/datepicker/date-range-input.spec.ts index e6ef835d498c..7db192b519a4 100644 --- a/src/material/datepicker/date-range-input.spec.ts +++ b/src/material/datepicker/date-range-input.spec.ts @@ -475,6 +475,24 @@ describe('MatDateRangeInput', () => { expect(fixture.componentInstance.end).toBe(end); })); + it('should preserve the values when assigning both together through ngModel', fakeAsync(() => { + const assignAndAssert = (start: Date, end: Date) => { + fixture.componentInstance.start = start; + fixture.componentInstance.end = end; + fixture.detectChanges(); + tick(); + fixture.detectChanges(); + expect(fixture.componentInstance.start).toBe(start); + expect(fixture.componentInstance.end).toBe(end); + }; + + const fixture = createComponent(RangePickerNgModel); + fixture.detectChanges(); + + assignAndAssert(new Date(2020, 1, 2), new Date(2020, 1, 5)); + assignAndAssert(new Date(2020, 2, 2), new Date(2020, 2, 5)); + })); + it('should move focus to the start input when pressing backspace on an empty end input', () => { const fixture = createComponent(StandardRangePicker); fixture.detectChanges(); diff --git a/src/material/datepicker/datepicker-input-base.ts b/src/material/datepicker/datepicker-input-base.ts index d137d69d9c22..8775f8c57f1f 100644 --- a/src/material/datepicker/datepicker-input-base.ts +++ b/src/material/datepicker/datepicker-input-base.ts @@ -125,7 +125,7 @@ export abstract class MatDatepickerInputBase {}; _validatorOnChange = () => {}; - private _cvaOnChange: (value: any) => void = () => {}; + protected _cvaOnChange: (value: any) => void = () => {}; private _valueChangesSubscription = Subscription.EMPTY; private _localeSubscription = Subscription.EMPTY;