Vaadin Flow DateTimePicker грязный внутри CRUD

#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 my pom.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 с соответствующим исправлением.