#vaadin #crud #datetimepicker #vaadin-flow
Вопрос:
Я добавляю a com.vaadin.flow.component.datetimepicker.DateTimePicker
к a com.vaadin.flow.component.crud.Crud
. Похоже, что это всегда помечает грязный CRUD. Я заметил, что при использовании a все хорошо com.vaadin.flow.component.datepicker.DatePicker
. Эта проблема проявляется только для DateTimePicker
. Как я должен справиться с этим?
DateTimePicker dtp = new DateTimePicker("When");
dtp.setStep(Duration.ofMillis(1));
// ...
binder.bind(dtp, new ValueProvider<MyEvent, LocalDateTime>() {
@Override
public LocalDateTime apply(final MyEvent source) {
return source.getWhen();
}
}, ...
Итак, DateTimePicker
с шагом в миллисекунду, при условии LocalDateTime
значения.
Позднее редактирование: я более подробно изучил DateTimePicker.setPresentationValue(LocalDateTime)
реализацию и обнаружил, что выполняется некоторый JavaScript:
datePicker.getElement().executeJs("this.dispatchEvent(new CustomEvent('change', { bubbles: true }));");
Может ли это быть так? К сожалению, я не знаком с внутренними компонентами Vaadin, поэтому не уверен, зачем это там требуется.
Комментарии:
1. Какую версию Vaadin вы используете? Потому что у DateTimePicker были некоторые пакеты в самой последней версии
2. Использование Vaadin 14.7.0
3. Не могли бы вы попробовать это с 14.7.2?
4. Да, я переключился на
<vaadin.version>14.7.2</vaadin.version>
in mypom.xml
, но ничего не изменилось.
Ответ №1:
Я испытал такое же поведение и на других компонентах (например, EnhancedDateTimePicker и автозаполнение). В какой-то ситуации происходит ValueChangeEvent, который запускается с клиента, даже если значение вообще не изменилось. Это делает поле грязным, и при использовании binder это приводит binder.hasChanges()
к возвращению true.
Я нашел обходной путь, создав пользовательский компонент, содержащий два экземпляра компонента. Один скрыт (не виден) и обновляется только тогда, когда значение видимого значения действительно изменяется. С точки зрения связующего (и любого другого внешнего), именно скрытый компонент предоставляет значение и события.
Здесь это для EnhancedDateTimePicker:
public class DateTimeSelection extends HorizontalLayout implements
HasValue<AbstractField.ComponentValueChangeEvent<EnhancedDateTimePicker, LocalDateTime>, LocalDateTime> {
private EnhancedDateTimeField hiddenDateTimeField = new EnhancedDateTimeField("");
private EnhancedDateTimeField visibleDateTimeField = new EnhancedDateTimeField("");
public DateTimeSelection() {
visibleDateTimeField.addValueChangeListener(event -> {
if (!ObjUtils.eq(event.getValue(), hiddenDateTimeField.getValue())) {
hiddenDateTimeField.setValue(event.getValue());
}
});
visibleDateTimeField.setWidthFull();
add(visibleDateTimeField);
}
public DateTimeSelection(String label) {
this();
setLabel(label);
}
public String getLabel() {
return visibleDateTimeField.getLabel();
}
public void setLabel(String label) {
visibleDateTimeField.setLabel(label);
}
@Override
public void setValue(LocalDateTime localDateTime) {
hiddenDateTimeField.setValue(localDateTime);
visibleDateTimeField.setValue(localDateTime);
}
@Override
public LocalDateTime getValue() {
return hiddenDateTimeField.getValue();
}
@Override
public LocalDateTime getEmptyValue() {
return hiddenDateTimeField.getEmptyValue();
}
@Override
public Optional<LocalDateTime> getOptionalValue() {
return hiddenDateTimeField.getOptionalValue();
}
@Override
public boolean isEmpty() {
return hiddenDateTimeField.isEmpty();
}
@Override
public void clear() {
hiddenDateTimeField.clear();
visibleDateTimeField.clear();
}
@Override
public void setReadOnly(boolean b) {
visibleDateTimeField.setReadOnly(b);
}
@Override
public boolean isReadOnly() {
return visibleDateTimeField.isReadOnly();
}
@Override
public void setRequiredIndicatorVisible(boolean b) {
visibleDateTimeField.setRequiredIndicatorVisible(b);
}
@Override
public boolean isRequiredIndicatorVisible() {
return visibleDateTimeField.isRequiredIndicatorVisible();
}
@Override
public Registration addValueChangeListener(ValueChangeListener<? super AbstractField.ComponentValueChangeEvent<EnhancedDateTimePicker, LocalDateTime>> valueChangeListener) {
return hiddenDateTimeField.addValueChangeListener(valueChangeListener);
}
}
Комментарии:
1. Спасибо, CT Liv! Я думал, что основные версии Vaadin (более) зрелые, но по мере изучения я понимаю, что это не так. Я не понимаю, почему у нас есть Vaadin Flow 21, а теперь 22 (альфа), когда 14 не хватает многих базовых функций и требует грязных исправлений то тут, то там. Я все больше и больше склоняюсь к тому, чтобы рассмотреть возможность использования Vaadin 8 вместо этого.
Ответ №2:
Пожалуйста, посмотрите https://github.com/vaadin/flow-components/issues/1043 . Вы должны иметь возможность изменять свой проект pom.xml чтобы выбрать версию v 14.7.1 компонента timepicker flow с соответствующим исправлением.