Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/material/datepicker/date-range-input-parts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ abstract class MatDateRangeInputPartBase<D>
return source !== this._rangeInput._startInput && source !== this._rangeInput._endInput;
}

protected override _assignValueProgrammatically(value: D | null) {
super._assignValueProgrammatically(value);
protected override _assignValueProgrammatically(value: D | null, reformat: boolean) {
super._assignValueProgrammatically(value, reformat);
const opposite = (
this === (this._rangeInput._startInput as MatDateRangeInputPartBase<D>)
? this._rangeInput._endInput
Expand Down
17 changes: 9 additions & 8 deletions src/material/datepicker/datepicker-input-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export abstract class MatDatepickerInputBase<S, D = ExtractDateTypeFromSelection
return this._model ? this._getValueFromModel(this._model.selection) : this._pendingValue;
}
set value(value: any) {
this._assignValueProgrammatically(value);
this._assignValueProgrammatically(value, true);
}
protected _model: MatDateSelectionModel<S, D> | undefined;

Expand Down Expand Up @@ -259,7 +259,7 @@ export abstract class MatDatepickerInputBase<S, D = ExtractDateTypeFromSelection

// Update the displayed date when the locale changes.
this._localeSubscription = this._dateAdapter.localeChanges.subscribe(() => {
this._assignValueProgrammatically(this.value);
this._assignValueProgrammatically(this.value, true);
});
}

Expand Down Expand Up @@ -293,10 +293,8 @@ export abstract class MatDatepickerInputBase<S, D = ExtractDateTypeFromSelection
writeValue(value: D): void {
// We produce a different date object on each keystroke which can cause signal forms'
// interop logic to keep calling `writeValue` with the same value as the user is typing.
// Skip such cases since they can prevent the user from typing (see #32442).
if (!value || value !== this.value) {
this._assignValueProgrammatically(value);
}
// Skip such cases since they can prevent the user from typing (see #32442 and #32475).
this._assignValueProgrammatically(value, value !== this.value);
}

/** Implemented as part of ControlValueAccessor. */
Expand Down Expand Up @@ -403,12 +401,15 @@ export abstract class MatDatepickerInputBase<S, D = ExtractDateTypeFromSelection
}

/** Programmatically assigns a value to the input. */
protected _assignValueProgrammatically(value: D | null) {
protected _assignValueProgrammatically(value: D | null, reformat: boolean) {
value = this._dateAdapter.deserialize(value);
this._lastValueValid = this._isValidValue(value);
value = this._dateAdapter.getValidDateOrNull(value);
this._assignValue(value);
this._formatValue(value);

if (reformat) {
this._formatValue(value);
}
}

/** Gets whether a value matches the current date filter. */
Expand Down
15 changes: 15 additions & 0 deletions src/material/datepicker/datepicker.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,21 @@ describe('MatDatepicker', () => {

expect(input.value).toBe('foo');
});

it('should not re-format the input value if the forms module re-assigns null', () => {
const input = fixture.nativeElement.querySelector('input');
testComponent.formControl.setValue(null);
fixture.detectChanges();
expect(input.value).toBe('');

// Note: this isn't how users would behave, but it captures
// the sequence of events with signal forms.
input.value = 'foo';
testComponent.formControl.setValue(null);
fixture.detectChanges();

expect(input.value).toBe('foo');
});
});

describe('datepicker with mat-datepicker-toggle', () => {
Expand Down
Loading