diff --git a/vaadin-date-picker-flow-parent/vaadin-date-picker-flow/src/main/java/com/vaadin/flow/component/datepicker/DatePicker.java b/vaadin-date-picker-flow-parent/vaadin-date-picker-flow/src/main/java/com/vaadin/flow/component/datepicker/DatePicker.java index de34cc163f2..dac11ff864a 100644 --- a/vaadin-date-picker-flow-parent/vaadin-date-picker-flow/src/main/java/com/vaadin/flow/component/datepicker/DatePicker.java +++ b/vaadin-date-picker-flow-parent/vaadin-date-picker-flow/src/main/java/com/vaadin/flow/component/datepicker/DatePicker.java @@ -56,6 +56,7 @@ import com.vaadin.flow.component.shared.InputField; import com.vaadin.flow.component.shared.ValidationUtil; import com.vaadin.flow.component.shared.internal.ValidationController; +import com.vaadin.flow.data.binder.Binder; import com.vaadin.flow.data.binder.HasValidator; import com.vaadin.flow.data.binder.ValidationResult; import com.vaadin.flow.data.binder.ValidationStatusChangeEvent; @@ -82,6 +83,46 @@ * the format of the current locale or through the date picker overlay. The * overlay opens when the field is clicked and/or any input is entered when the * field is focused. + *
+ * Date Picker comes with a built-in validation mechanism based on constraints. + * Validation is triggered whenever the user initiates a date change, for + * example by selection from the overlay or manual entry followed by Enter or + * blur. Programmatic value changes trigger validation as well. + *
+ * Validation verifies that the value is parsable into {@link LocalDate} and + * satisfies the specified constraints. If validation fails, the component is + * marked as invalid and an error message is displayed below the input. + *
+ * The following constraints are supported: + *
+ * Error messages for unparsable input and constraints can be configured with + * the {@link DatePickerI18n} object, using the respective properties. If you + * want to provide a single catch-all error message, you can also use the + * {@link #setErrorMessage(String)} method. Note that such an error message will + * take priority over i18n error messages if both are set. + *
+ * In addition to validation, constraints may also have a visual aspect. For + * example, dates before the minimum date are displayed as disabled in the + * overlay to prevent their selection. + *
+ * For more advanced validation that requires custom rules, you can use + * {@link Binder}. By default, before running custom validators, Binder will + * also check if the date is parsable and satisfies the component constraints, + * displaying error messages from the {@link DatePickerI18n} object. The + * exception is the required constraint, for which Binder provides its own API, + * see {@link Binder.BindingBuilder#asRequired(String) asRequired()}. + *
+ * However, if Binder doesn't fit your needs and you want to implement fully + * custom validation logic, you can disable the constraint validation by setting + * {@link #setManualValidation(boolean)} to true. This will allow you to control + * the invalid state and the error message manually using + * {@link #setInvalid(boolean)} and {@link #setErrorMessage(String)} API. * * @author Vaadin Ltd */ @@ -340,12 +381,29 @@ public DatePicker(LocalDate initialDate, Locale locale) { } /** - * Sets the minimum date in the date picker. Dates before that will be - * disabled in the popup. + * {@inheritDoc} + *
+ * Distinct error messages for unparsable input and different constraints + * can be configured with the {@link DatePickerI18n} object, using the + * respective properties. However, note that the error message set with + * {@link #setErrorMessage(String)} will take priority and override any i18n + * error messages if both are set. + */ + @Override + public void setErrorMessage(String errorMessage) { + HasValidationProperties.super.setErrorMessage(errorMessage); + } + + /** + * Sets the minimum date allowed to be selected for this field. Dates before + * that will be disabled in the calendar overlay. Manual entry of such dates + * will cause the component to invalidate. + *
+ * The minimum date is inclusive.
*
* @param min
- * the minimum date that is allowed to be selected, or
- * null
to remove any minimum constraints
+ * the minimum date, or {@code null} to remove this constraint
+ * @see DatePickerI18n#setMinErrorMessage(String)
*/
public void setMin(LocalDate min) {
String minAsString = FORMATTER.apply(min);
@@ -354,23 +412,25 @@ public void setMin(LocalDate min) {
}
/**
- * Gets the minimum date in the date picker. Dates before that will be
- * disabled in the popup.
+ * Gets the minimum date allowed to be selected for this field.
*
- * @return the minimum date that is allowed to be selected, or
- * null
if there's no minimum
+ * @return the minimum date, or {@code null} if no minimum is set
+ * @see #setMax(LocalDate)
*/
public LocalDate getMin() {
return PARSER.apply(getElement().getProperty("min"));
}
/**
- * Sets the maximum date in the date picker. Dates after that will be
- * disabled in the popup.
+ * Sets the maximum date allowed to be selected for this field. Dates after
+ * that will be disabled in the calendar overlay. Manual entry of such dates
+ * will cause the component to invalidate.
+ *
+ * The maximum date is inclusive.
*
* @param max
- * the maximum date that is allowed to be selected, or
- * null
to remove any maximum constraints
+ * the maximum date, or {@code null} to remove this constraint
+ * @see DatePickerI18n#setMaxErrorMessage(String)
*/
public void setMax(LocalDate max) {
String maxAsString = FORMATTER.apply(max);
@@ -379,11 +439,10 @@ public void setMax(LocalDate max) {
}
/**
- * Gets the maximum date in the date picker. Dates after that will be
- * disabled in the popup.
+ * Gets the maximum date allowed to be selected for this field.
*
- * @return the maximum date that is allowed to be selected, or
- * null
if there's no maximum
+ * @return the maximum date, or {@code null} if no maximum is set
+ * @see #setMax(LocalDate)
*/
public LocalDate getMax() {
return PARSER.apply(getElement().getProperty("max"));
@@ -686,22 +745,49 @@ public LocalDate getInitialPosition() {
}
/**
- * Sets whether the date picker is marked as input required.
+ * Sets whether the user is required to provide a value. When required, an
+ * indicator appears next to the label and the field invalidates if the
+ * value is cleared.
+ *
+ * NOTE: The required indicator is only visible when the field has a label, + * see {@link #setLabel(String)}. * * @param required - * the boolean value to set + * {@code true} to make the field required, {@code false} + * otherwise + * @see DatePickerI18n#setRequiredErrorMessage(String) + */ + @Override + public void setRequiredIndicatorVisible(boolean required) { + super.setRequiredIndicatorVisible(required); + } + + /** + * Gets whether the user is required to provide a value. + * + * @return {@code true} if the field is required, {@code false} otherwise + * @see #setRequiredIndicatorVisible(boolean) + */ + @Override + public boolean isRequiredIndicatorVisible() { + return super.isRequiredIndicatorVisible(); + } + + /** + * Alias for {@link #setRequiredIndicatorVisible(boolean)}. + * + * @param required + * {@code true} to make the field required, {@code false} + * otherwise */ public void setRequired(boolean required) { setRequiredIndicatorVisible(required); } /** - * Determines whether the datepicker is marked as input required. - *
- * This property is not synchronized automatically from the client side, so - * the returned value may not be the same as in client side. + * Alias for {@link #isRequiredIndicatorVisible()} * - * @return {@code true} if the input is required, {@code false} otherwise + * @return {@code true} if the field is required, {@code false} otherwise */ public boolean isRequired() { return isRequiredIndicatorVisible(); diff --git a/vaadin-time-picker-flow-parent/vaadin-time-picker-flow/src/main/java/com/vaadin/flow/component/timepicker/TimePicker.java b/vaadin-time-picker-flow-parent/vaadin-time-picker-flow/src/main/java/com/vaadin/flow/component/timepicker/TimePicker.java index 0967e1ec683..8d093734943 100644 --- a/vaadin-time-picker-flow-parent/vaadin-time-picker-flow/src/main/java/com/vaadin/flow/component/timepicker/TimePicker.java +++ b/vaadin-time-picker-flow-parent/vaadin-time-picker-flow/src/main/java/com/vaadin/flow/component/timepicker/TimePicker.java @@ -52,6 +52,7 @@ import com.vaadin.flow.component.shared.InputField; import com.vaadin.flow.component.shared.ValidationUtil; import com.vaadin.flow.component.shared.internal.ValidationController; +import com.vaadin.flow.data.binder.Binder; import com.vaadin.flow.data.binder.HasValidator; import com.vaadin.flow.data.binder.ValidationResult; import com.vaadin.flow.data.binder.ValidationStatusChangeEvent; @@ -67,6 +68,46 @@ * time can be entered directly using a keyboard or by choosing a value from a * set of predefined options presented in an overlay. The overlay opens when the * field is clicked or any input is entered when the field is focused. + *
+ * Time Picker comes with a built-in validation mechanism based on constraints. + * Validation is triggered whenever the user initiates a time change, for + * example by selection from the dropdown or manual entry followed by Enter or + * blur. Programmatic value changes trigger validation as well. + *
+ * Validation verifies that the value is parsable into {@link LocalTime} and + * satisfies the specified constraints. If validation fails, the component is + * marked as invalid and an error message is displayed below the input. + *
+ * The following constraints are supported: + *
+ * Error messages for unparsable input and constraints can be configured with + * the {@link TimePickerI18n} object, using the respective properties. If you + * want to provide a single catch-all error message, you can also use the + * {@link #setErrorMessage(String)} method. Note that such an error message will + * take priority over i18n error messages if both are set. + *
+ * In addition to validation, constraints may also have a visual impact. For + * example, times before the minimum time or after the maximum time are not + * displayed in the dropdown to prevent their selection. + *
+ * For more advanced validation that requires custom rules, you can use + * {@link Binder}. By default, before running custom validators, Binder will + * also check if the time is parsable and satisfies the component constraints, + * displaying error messages from the {@link TimePickerI18n} object. The + * exception is the required constraint, for which Binder provides its own API, + * see {@link Binder.BindingBuilder#asRequired(String) asRequired()}. + *
+ * However, if Binder doesn't fit your needs and you want to implement fully + * custom validation logic, you can disable the constraint validation by setting + * {@link #setManualValidation(boolean)} to true. This will allow you to control + * the invalid state and the error message manually using + * {@link #setInvalid(boolean)} and {@link #setErrorMessage(String)} API. * * @author Vaadin Ltd */ @@ -276,6 +317,20 @@ public TimePicker(String label, LocalTime time, addValueChangeListener(listener); } + /** + * {@inheritDoc} + *
+ * Distinct error messages for unparsable input and different constraints + * can be configured with the {@link TimePickerI18n} object, using the + * respective properties. However, note that the error message set with + * {@link #setErrorMessage(String)} will take priority and override any i18n + * error messages if both are set. + */ + @Override + public void setErrorMessage(String errorMessage) { + HasValidationProperties.super.setErrorMessage(errorMessage); + } + /** * Sets the label for the time picker. * @@ -404,22 +459,49 @@ protected boolean isInputValuePresent() { } /** - * Sets whether the time picker is marked as input required. + * Sets whether the user is required to provide a value. When required, an + * indicator appears next to the label and the field invalidates if the + * value is cleared. + *
+ * NOTE: The required indicator is only visible when the field has a label, + * see {@link #setLabel(String)}. * * @param required - * the boolean value to set + * {@code true} to make the field required, {@code false} + * otherwise + * @see TimePickerI18n#setRequiredErrorMessage(String) + */ + @Override + public void setRequiredIndicatorVisible(boolean required) { + super.setRequiredIndicatorVisible(required); + } + + /** + * Gets whether the user is required to provide a value. + * + * @return {@code true} if the field is required, {@code false} otherwise + * @see #setRequiredIndicatorVisible(boolean) + */ + @Override + public boolean isRequiredIndicatorVisible() { + return super.isRequiredIndicatorVisible(); + } + + /** + * Alias for {@link #setRequiredIndicatorVisible(boolean)}. + * + * @param required + * {@code true} to make the field required, {@code false} + * otherwise */ public void setRequired(boolean required) { setRequiredIndicatorVisible(required); } /** - * Determines whether the time picker is marked as input required. - *
- * This property is not synchronized automatically from the client side, so - * the returned value may not be the same as in client side. + * Alias for {@link #isRequiredIndicatorVisible()} * - * @return {@code true} if the input is required, {@code false} otherwise + * @return {@code true} if the field is required, {@code false} otherwise */ public boolean isRequired() { return isRequiredIndicatorVisible(); @@ -620,12 +702,15 @@ private void executeLocaleUpdate() { } /** - * Sets the minimum time in the time picker. Times before that will be - * disabled in the popup. + * Sets the minimum time allowed to be selected for this field. Times before + * that won't be displayed in the dropdown. Manual entry of such times will + * cause the component to invalidate. + *
+ * The minimum time is inclusive.
*
* @param min
- * the minimum time that is allowed to be selected, or
- * null
to remove any minimum constraints
+ * the minimum time, or {@code null} to remove this constraint
+ * @see TimePickerI18n#setMinErrorMessage(String)
*/
public void setMin(LocalTime min) {
this.min = min;
@@ -634,23 +719,25 @@ public void setMin(LocalTime min) {
}
/**
- * Gets the minimum time in the time picker. Time before that will be
- * disabled in the popup.
+ * Gets the minimum time allowed to be selected for this field.
*
- * @return the minimum time that is allowed to be selected, or
- * null
if there's no minimum
+ * @return the minimum time, or {@code null} if no minimum is set
+ * @see #setMax(LocalTime)
*/
public LocalTime getMin() {
return this.min;
}
/**
- * Sets the maximum time in the time picker. Times after that will be
- * disabled in the popup.
+ * Sets the maximum time allowed to be selected for this field. Times after
+ * that won't be displayed in the dropdown. Manual entry of such times will
+ * cause the component to invalidate.
+ *
+ * The maximum time is inclusive.
*
* @param max
- * the maximum time that is allowed to be selected, or
- * null
to remove any maximum constraints
+ * the maximum time, or {@code null} to remove this constraint
+ * @see TimePickerI18n#setMaxErrorMessage(String)
*/
public void setMax(LocalTime max) {
this.max = max;
@@ -659,11 +746,10 @@ public void setMax(LocalTime max) {
}
/**
- * Gets the maximum time in the time picker. Times after that will be
- * disabled in the popup.
+ * Gets the maximum time allowed to be selected for this field.
*
- * @return the maximum time that is allowed to be selected, or
- * null
if there's no maximum
+ * @return the maximum time, or {@code null} if no maximum is set
+ * @see #setMin(LocalTime)
*/
public LocalTime getMax() {
return this.max;