Open mab-infokom opened 1 year ago
You should use Binder and enable enforceFieldValidation=true in feature flags in src/main/resources/vaadin-featureflags.properties file.
com.vaadin.experimental.enforceFieldValidation=true See more at: https://github.com/vaadin/platform/issues/3066
That is a new feature we have developed exactly for this kind of use. I.e. to detect input of wrong format in DatePicker or some other fields.
Also it is possible to use DatePicker#addClientValidatedEventListener to detect changes when not using Binder.
The question is actually about race condition when using key shortcuts. Here is a more simplified example of the case, which has been solved by using empty JavaScript call to post pone activity to the next roundtrip. This way get correct value.
package org.vaadin.tatu;
import java.time.LocalDate;
import com.vaadin.flow.component.Key;
import com.vaadin.flow.component.KeyModifier;
import com.vaadin.flow.component.Shortcuts;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.ValidationException;
import com.vaadin.flow.router.Route;
@Route("form")
public class DatePickerView extends Div {
public class Person {
private LocalDate birthDate;
private String name;
public LocalDate getBirthDate() {
return birthDate;
}
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public DatePickerView() {
DatePicker datePicker = new DatePicker("Birth date");
TextField textField = new TextField("Name");
Person person = new Person();
Binder<Person> binder = new Binder<>();
binder.forField(datePicker).asRequired().bind(Person::getBirthDate,
Person::setBirthDate);
binder.forField(textField).asRequired().bind(Person::getName,
Person::setName);
binder.readBean(person);
Button save = new Button("Save");
save.addClickListener(e -> {
try {
binder.writeBean(person);
Notification.show("'" + person.getName() + " "
+ person.getBirthDate().toString() + "' saved!");
} catch (ValidationException e1) {
Notification.show("Not valid");
}
});
Shortcuts.addShortcutListener(save, e -> {
datePicker.setOpened(false);
datePicker.getElement().executeJs("return 0;").then(result -> {
save.focus();
save.click();
});
}, Key.KEY_S, KeyModifier.CONTROL).listenOn(this);
add(textField, datePicker, save);
}
}
Description
We are setting up a Vaadin Renderer for our business applications and are struggling with DatePicker currently.
When starting with empty DatePicker Fields, the user can enter a new value on the fly - let's say "17.02.2023".
Now the user has many options that need us to get the entered value.
In all those cases, he did not "finish" his input by typing ENTER, which would cause DatePicker to update its internal value.
Let's take STRG + S as an example:
When our save code runs, it needs current user input in the date field. But there is no way to get it, as DatePicker provides old null value.
We reached out to the Vaadin Chat and got first workaround idea, wich is not suitable for us, but makes this issue reproducable.
Expected outcome
We would expect, that we can access valid user input somehow when pressing STRG+S and our save code runs. If user input is not valid, we should be able to recognize this as well in order to abort saving process. As DatePicker has not processed the user input in our use case, we are stuck.
Minimal reproducible example
Steps to reproduce
Environment
Vaadin Version 23.3.6 OS Linux and Windows
Browsers
Chrome, Firefox, Safari on iOS