问题
When I try to use a line-based editor (setEditorEnabled(true), Buffered Mode), I get an error:
Caused by: com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type java.time.LocalTime to presentation type class java.lang.String. No converter is set and the types are not compatible.
at com.vaadin.data.util.converter.ConverterUtil.convertFromModel(ConverterUtil.java:116) ~[vaadin-server-7.6.8.jar:7.6.8]
Grid initialization:
BeanItemContainer<MealTo> container = new BeanItemContainer<>(MealTo.class);
Grid grid = new Grid();
grid.setContainerDataSource(container);
grid.setEditorEnabled(true);
grid.setSelectionMode(Grid.SelectionMode.NONE);
grid.getColumn("time")
.setMinimumWidth(100)
.setConverter(new StringToLocalTimeConverter())
.setResizable(false);
...
Converter:
public class StringToLocalTimeConverter implements Converter<String, LocalTime> {
public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");
@Override
public LocalTime convertToModel(String value, Class<? extends LocalTime> targetType, Locale locale) throws ConversionException {
return LocalTime.parse(value, TIME_FORMATTER);
}
@Override
public String convertToPresentation(LocalTime value, Class<? extends String> targetType, Locale locale) throws ConversionException {
return value.format(TIME_FORMATTER);
}
@Override
public Class<LocalTime> getModelType() {
return LocalTime.class;
}
@Override
public Class<String> getPresentationType() {
return String.class;
}
}
Does anyone know how to fix this? Thanks
回答1:
I tried and got the same issue, filtered/relevant stacktrace below
com.vaadin.data.Buffered$SourceException: null
at com.vaadin.ui.AbstractField.setPropertyDataSource(AbstractField.java:665) ~[vaadin-server-7.6.8.jar:7.6.8]
at com.vaadin.data.fieldgroup.FieldGroup.bind(FieldGroup.java:278) ~[vaadin-server-7.6.8.jar:7.6.8]
at com.vaadin.data.fieldgroup.FieldGroup.buildAndBind(FieldGroup.java:1190) ~[vaadin-server-7.6.8.jar:7.6.8]
at com.vaadin.data.fieldgroup.FieldGroup.buildAndBind(FieldGroup.java:1168) ~[vaadin-server-7.6.8.jar:7.6.8]
at com.vaadin.data.fieldgroup.FieldGroup.buildAndBind(FieldGroup.java:1150) ~[vaadin-server-7.6.8.jar:7.6.8]
at com.vaadin.ui.Grid.getEditorField(Grid.java:6752) ~[vaadin-server-7.6.8.jar:7.6.8]
at com.vaadin.ui.Grid.doEditItem(Grid.java:6805) ~[vaadin-server-7.6.8.jar:7.6.8]
at com.vaadin.ui.Grid$4.doBind(Grid.java:4772) ~[vaadin-server-7.6.8.jar:7.6.8]
at com.vaadin.ui.Grid$4.bind(Grid.java:4761) ~[vaadin-server-7.6.8.jar:7.6.8]
... 40 irrelevant lines removed
Caused by: com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type java.time.LocalTime to presentation type class java.lang.String. No converter is set and the types are not compatible.
at com.vaadin.data.util.converter.ConverterUtil.convertFromModel(ConverterUtil.java:116) ~[vaadin-server-7.6.8.jar:7.6.8]
at com.vaadin.ui.AbstractField.convertFromModel(AbstractField.java:736) ~[vaadin-server-7.6.8.jar:7.6.8]
at com.vaadin.ui.AbstractField.convertFromModel(AbstractField.java:721) ~[vaadin-server-7.6.8.jar:7.6.8]
at com.vaadin.ui.AbstractField.setPropertyDataSource(AbstractField.java:657) ~[vaadin-server-7.6.8.jar:7.6.8]
... 48 common frames omitted
So it would seem that converters defined for columns are not inherited in editor generated fields (as one would might expect.. maybe?!).
Nonetheless, if you manually define an editor field and assign it the same converter, then it should work as expected. Full sample below, including a minor update in the converter to support default empty values:
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.ui.Grid;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class GridWithLocalTimeField extends VerticalLayout {
public GridWithLocalTimeField() {
// basic grid setup, double click row to edit
BeanItemContainer<MyBean> container = new BeanItemContainer<>(MyBean.class);
Grid grid = new Grid();
grid.setContainerDataSource(container);
grid.setEditorEnabled(true);
grid.setSelectionMode(Grid.SelectionMode.SINGLE);
addComponent(grid);
// add a custom field for editing the LocalTime field
TextField dateFieldEditor = new TextField();
dateFieldEditor.setConverter(new StringToLocalTimeConverter());
// configure grid column for the LocalTime field
grid.getColumn("time")
.setMinimumWidth(100)
.setConverter(new StringToLocalTimeConverter())
.setResizable(false)
.setEditorField(dateFieldEditor); // comment this to get the stacktrace
// add some dummy data
for (int i = 0; i < 10; i++) {
container.addBean(new MyBean(LocalTime.now(), i));
}
}
public static class StringToLocalTimeConverter implements Converter<String, LocalTime> {
public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");
@Override
public LocalTime convertToModel(String value, Class<? extends LocalTime> targetType, Locale locale) throws ConversionException {
if (value == null || value.isEmpty()) {
return null;
} else {
return LocalTime.parse(value, TIME_FORMATTER);
}
}
@Override
public String convertToPresentation(LocalTime value, Class<? extends String> targetType, Locale locale) throws ConversionException {
if (value == null) {
return "";
} else {
return value.format(TIME_FORMATTER);
}
}
@Override
public Class<LocalTime> getModelType() {
return LocalTime.class;
}
@Override
public Class<String> getPresentationType() {
return String.class;
}
}
public static class MyBean {
private LocalTime time;
private int order;
public MyBean(LocalTime time, int order) {
this.time = time;
this.order = order;
}
public LocalTime getTime() {
return time;
}
public void setTime(LocalTime time) {
this.time = time;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
}
}
Result:
来源:https://stackoverflow.com/questions/38862644/vaadin-grid-how-to-use-bean-with-localtime-field-in-line-based-editor