Vaadin Flow DateTimePicker 在 CRUD 中变脏
Vaadin Flow DateTimePicker dirty inside CRUD
我正在将 com.vaadin.flow.component.datetimepicker.DateTimePicker
添加到 com.vaadin.flow.component.crud.Crud
。这似乎总是将 CRUD 标记为脏。我注意到使用 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 的内部结构,所以不确定为什么在那里需要它。
我在其他组件上也遇到过相同的行为(例如:EnhancedDateTimePicker and Autocomplete)。在某些情况下,即使值根本没有更改,也会从客户端触发 ValueChangeEvent。这会使该字段变脏并使用活页夹这会产生 binder.hasChanges()
returns 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);
}
}
请参阅 https://github.com/vaadin/flow-components/issues/1043。您应该能够通过适当的修复将项目的 pom.xml 更改为 pick-up v 14.7.1 版本的时间选择器流组件。
我正在将 com.vaadin.flow.component.datetimepicker.DateTimePicker
添加到 com.vaadin.flow.component.crud.Crud
。这似乎总是将 CRUD 标记为脏。我注意到使用 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 的内部结构,所以不确定为什么在那里需要它。
我在其他组件上也遇到过相同的行为(例如:EnhancedDateTimePicker and Autocomplete)。在某些情况下,即使值根本没有更改,也会从客户端触发 ValueChangeEvent。这会使该字段变脏并使用活页夹这会产生 binder.hasChanges()
returns 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);
}
}
请参阅 https://github.com/vaadin/flow-components/issues/1043。您应该能够通过适当的修复将项目的 pom.xml 更改为 pick-up v 14.7.1 版本的时间选择器流组件。