Skip to content

Commit 7dd08db

Browse files
committed
fix(material/datepicker): value reset when invalid value is entered using signal forms
Fixes that the datepicker input value was being reset when the user types in an invalid date while using signal forms. Fixes #32475.
1 parent 76f2603 commit 7dd08db

File tree

3 files changed

+26
-10
lines changed

3 files changed

+26
-10
lines changed

src/material/datepicker/date-range-input-parts.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ abstract class MatDateRangeInputPartBase<D>
186186
return source !== this._rangeInput._startInput && source !== this._rangeInput._endInput;
187187
}
188188

189-
protected override _assignValueProgrammatically(value: D | null) {
190-
super._assignValueProgrammatically(value);
189+
protected override _assignValueProgrammatically(value: D | null, reformat: boolean) {
190+
super._assignValueProgrammatically(value, reformat);
191191
const opposite = (
192192
this === (this._rangeInput._startInput as MatDateRangeInputPartBase<D>)
193193
? this._rangeInput._endInput

src/material/datepicker/datepicker-input-base.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export abstract class MatDatepickerInputBase<S, D = ExtractDateTypeFromSelection
9494
return this._model ? this._getValueFromModel(this._model.selection) : this._pendingValue;
9595
}
9696
set value(value: any) {
97-
this._assignValueProgrammatically(value);
97+
this._assignValueProgrammatically(value, true);
9898
}
9999
protected _model: MatDateSelectionModel<S, D> | undefined;
100100

@@ -259,7 +259,7 @@ export abstract class MatDatepickerInputBase<S, D = ExtractDateTypeFromSelection
259259

260260
// Update the displayed date when the locale changes.
261261
this._localeSubscription = this._dateAdapter.localeChanges.subscribe(() => {
262-
this._assignValueProgrammatically(this.value);
262+
this._assignValueProgrammatically(this.value, true);
263263
});
264264
}
265265

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

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

405403
/** Programmatically assigns a value to the input. */
406-
protected _assignValueProgrammatically(value: D | null) {
404+
protected _assignValueProgrammatically(value: D | null, reformat: boolean) {
407405
value = this._dateAdapter.deserialize(value);
408406
this._lastValueValid = this._isValidValue(value);
409407
value = this._dateAdapter.getValidDateOrNull(value);
410408
this._assignValue(value);
411-
this._formatValue(value);
409+
410+
if (reformat) {
411+
this._formatValue(value);
412+
}
412413
}
413414

414415
/** Gets whether a value matches the current date filter. */

src/material/datepicker/datepicker.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,21 @@ describe('MatDatepicker', () => {
11761176

11771177
expect(input.value).toBe('foo');
11781178
});
1179+
1180+
it('should not re-format the input value if the forms module re-assigns null', () => {
1181+
const input = fixture.nativeElement.querySelector('input');
1182+
testComponent.formControl.setValue(null);
1183+
fixture.detectChanges();
1184+
expect(input.value).toBe('');
1185+
1186+
// Note: this isn't how users would behave, but it captures
1187+
// the sequence of events with signal forms.
1188+
input.value = 'foo';
1189+
testComponent.formControl.setValue(null);
1190+
fixture.detectChanges();
1191+
1192+
expect(input.value).toBe('foo');
1193+
});
11791194
});
11801195

11811196
describe('datepicker with mat-datepicker-toggle', () => {

0 commit comments

Comments
 (0)