Skip to content

Regression: MatDatepickerInput (Angular Material 21) keeps invalid text visible after blur when the parsed value is null #33610

Description

@marcelhoelscher

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

Angular Material 19

Description

Our application uses a custom blur handler to clear invalid date input for date fields.

This behavior was not provided by Angular Material by default. We explicitly implemented it in our date component by calling setValue(null, { emitModelToViewChange: true }) when the parsed form-control value is null.

This worked with Angular Material 19.2.17, but no longer works after upgrading to Angular Material 21.2.13.

The application code itself has not changed in any relevant way.

Application code

Our date component contains the following method:

onInputValueChanged(): void {
  super.onInputValueChanged();

  if (!this.inputControl.value) {
    this.inputControl.setValue(null, {
      emitEvent: false,
      emitModelToViewChange: true
    });
  }
}

The method is called when the input loses focus:

<input
  [formControl]="inputControl"
  [matDatepicker]="matDatePicker"
  (blur)="onInputValueChanged()"
  (dateChange)="onInputValueChanged()" />

Reproduction

Stackblitz-Link: https://stackblitz.com/edit/datepicker-clear-invalid-input-21

Steps to reproduce:

  1. Enter an invalid value ('abc') into the text field and step out
  2. Input field is not cleared

Expected Behavior

Invalid input in the input field gets cleared.

You can reproduce the desired behavior here: https://stackblitz.com/edit/datepicker-clear-invalid-input-19

It's the same code as in the https://stackblitz.com/edit/datepicker-clear-invalid-input-21 demo - but with Angular Material 19.

Actual Behavior

Invalid input is not cleared.

When you debug the code, you will notice the following:

As soon as you enter an invalid character, the value of the form control is internally set to null.

When the input loses focus, the application calls:

this.inputControl.setValue(null, {
  emitEvent: false,
  emitModelToViewChange: true
});

With Angular Material 19, this caused the model value to be written back to the view and cleared the native input element. The result was:

FormControl.value === null
native input.value === ""

With Angular 21, the input is still parsed and the form-control value is still set to null while typing.
However, after the input loses focus, the same application code no longer clears the visible text. The result is:

FormControl.value === null
native input.value === "abc"

This leaves the form-control value and the visible input value inconsistent.

Technical details:

During the blur handling in Angular Material 21, the following logic is executed (in datepicker.mjs):

this._assignValueProgrammatically(value, value !== this.value);

For an invalid input, both value and this.value are already null:

value === null
this.value === null
value !== this.value // false

Consequently, _assignValueProgrammatically is called with reformat === false:

_assignValueProgrammatically(value, reformat) {
  value = this._dateAdapter.deserialize(value);
  this._lastValueValid = this._isValidValue(value);
  value = this._dateAdapter.getValidDateOrNull(value);
  this._assignValue(value);

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

Since reformat is false, _formatValue(null) is not called.

The _formatValue method is responsible for clearing the native input:

In Angular Material 19, the call to this._formatValue(value)was executed regardless of the fact, if there is a diff between the form controls value and the value displayed.

Environment

  • Angular: 19 / 21
  • CDK/Material: 19 / 21
  • Browser(s): Chrome
  • Operating System (e.g. Windows, macOS, Ubuntu): MacOs, Windows 11

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions