Skip to content

Commit b1287cf

Browse files
committed
fix(material/datepicker): value reset when invalid value is entered using signal forms (#32485)
Fixes that the datepicker input value was being reset when the user types in an invalid date while using signal forms. Fixes #32475. (cherry picked from commit 29a8a2f)
1 parent 9a89c27 commit b1287cf

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)