DatePicker Min-Max Not Working

Title: DatePicker accepts out-of-range values entered from keyboard and fires ValueChangeEvent

Vaadin Version: 24.7.4

Description

I noticed a potentially unexpected behavior with DatePicker .

When min and max are configured, selecting a date through the date picker UI correctly restricts the user to the allowed range. However, when a date is entered manually from the keyboard, the component accepts a value outside the configured range and fires a ValueChangeEvent with that value.

Sample Code

DatePicker dp = new DatePicker();
add(dp);

dp.setMin(LocalDate.of(2026, 6, 5));
dp.setMax(LocalDate.of(2026, 6, 5));

dp.addValueChangeListener(event -> {
    System.out.println(event.getValue());
});

Steps to Reproduce

  1. Open the view containing the DatePicker .
  2. Focus the field.
  3. Type 2026-06-15 manually (or any date outside the configured range).
  4. Press Enter or move focus away.

Expected Behavior

Since both min and max are set to 2026-06-05 , I would expect values outside that range to be rejected, or at least not propagated as a valid value through ValueChangeEvent .

Actual Behavior

The listener receives:

2026-06-05
2026-06-15

even though 2026-06-15 is outside the configured range.

The component becomes invalid, but the out-of-range value is still set and delivered to the ValueChangeListener .

Is this the intended behavior, or should out-of-range values be prevented from being set as the component value?

That’s why you typically use Binder and proper binding and validation on that level. The underlying listener has to be called to trigger the invalid state and other mechanism where the wrong value is needed.

Hello @yasin.yildirim,

This is expected behavior with the current design of the field components, which DatePicker is one of. They implement a server-first approach to validation: every value change is sent to the server and validated there, regardless of whether it looks valid or not on the client side.

Skipping that synchronization would cause various sorts of inconsistencies. For example, let’s say a DatePicker already holds a valid value, and you then type a value that is out of range. If that change isn’t synchronized, the server would keep the old valid value while the client would show a completely different value plus an error message. Then, if you press the Submit button, the form may still submit successfully, because from the server’s perspective the last synchronized value is valid.

So, coming back to your example, my suggestion would instead be to detect and ignore these changes in your value change listener, which you can do by checking whether the component is valid, like so:

dp.addValueChangeListener(event -> {
    if (dp.isInvalid()) {
        return;
    }

    System.out.println(event.getValue());
});