vaadin / flow-components

Java counterpart of Vaadin Web Components
101 stars 66 forks source link

Error messages for constraints #4618

Open vursen opened 1 year ago

vursen commented 1 year ago

Describe your motivation

A follow-up to https://github.com/vaadin/platform/issues/3066

Every field component provides its own set of constraints such as setMinLength(...), setPattern(...), etc. Not long ago, we integrated component constraints into Binder validation but there's been no way to set up error messages for them since then. A red highlight is the only indication of constraint violations. That said, it's been possible to set up error messages for custom validators. As a result, the error messages may be inconsistent.

Error messages are integral in forms and constraints aren't an exception:

Example: You accidentally added extra spaces to a field that doesn't allow them due to a pattern constraint. It is really hard to notice the mistake without an explicit error message.

Example: DatePicker cannot parse “11th of December, 2023” because it is an invalid format. It looks however like a valid date, so just a red highlight isn't enough to figure out the mistake.

Describe the solution you'd like

We could add the second argument to constraint setters that would be used by getDefaultValidator() as an error message when returning a ValidationResult:

textField.setPattern("^\\d+$", "Must consist of digits");
passwordField.setMinLength(6, "Must have at least 6 characters");

The error messages added this way could be also shown during the built-in component constraint validation.

Describe alternatives you've considered

No response

Additional context

We need to consider that some might want to provide constraint error messages at the global level rather than for each individual field, so the implementation should apparently take this into account.

Related AC: https://github.com/vaadin/platform/issues/6707

knoobie commented 1 year ago

Probably related with additional API suggestions: https://github.com/vaadin/flow-components/pull/3406#discussion_r925934529

knoobie commented 1 year ago

Looking back at my comment from some month ago - instead of just another BiFunction, I would suggest to reuse Flow's ErrorMessageProvider as second param (for easier usage a simple String as second param should also work as overloaded method). To give Developers the full flexibility they are used by the Binder::withValidator API where this interface is also used.

gert-dubois commented 1 year ago

What is the status of this issue? For our current project being able to customize these error messages (especially the non-parsable error message) is considered quite important.

vursen commented 1 year ago

What is the status of this issue? For our current project being able to customize these error messages (especially the non-parsable error message) is considered quite important.

Unfortunately, most likely we won't be able to make it to 24.2, but it's on our backlog and we are aiming at getting it into 24.3.

vursen commented 11 months ago

I've opened a Github discussion with a proposal for error messages: https://github.com/orgs/vaadin/discussions/4664.

Any feedback is welcome.

vursen commented 9 months ago

A potential solution will involve adding an API to Binder to allow skipping the default validator to make it possible to define all error messages on Binder validators exclusively (https://github.com/vaadin/flow/issues/17178), and also adding a bad input validator for the relevant components.

vursen commented 4 months ago

We've agreed on the following API for now:

Example 1:

datePicker.setMin(minDate);
datePicker.getI18n().setBadInputErrorMessage("Date has incorrect format");
datePicker.getI18n().getBadInputErrorMessage();
datePicker.getI18n().setMinErrorMessage("Date must be later than " + minDate);
datePicker.getI18n().getMinErrorMessage();

Example 2 :

datePicker.setMin(minDate);
datePicker.getI18n().setBadInputErrorMessage("Date has incorrect format");
datePicker.getI18n().setMinErrorMessage("Date must be later than " + minDate);

binder.forField(datePicker)
        // Disable the default validator
    .withDefaultValidator(false)
        // Add a custom validator
    .withValidator(dateOrAnotherFieldPredicate, "You must fill either one field or another") 
        // Add the default validator manually. It will use error messages from the i18n object
    .withValidator(datePicker.getDefaultValidator()) 

Note, introducing constraint method overloads has been postponed. Implementing them now through i18n would require a breaking change later to support ErrorMessageProvider. We plan to revisit this when the Flow components fully integrate with the new i18n mechanism to explore other alternatives.