Vaadin Grid : How to use bean with LocalTime field in line-based editor?

流过昼夜 提交于 2020-02-24 10:04:08

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!