Vaadin 14 - 文本字段未正确显示枚举
Vaadin 14 - Text field not displaying enumeration correctly
我有一条信息作为字符串代码值存储在数据库中table。我定义了一个枚举以使代码易于阅读。实体 class 使用枚举定义字段。
当我在 Vaadin 网格中显示数据时,它显示枚举值,这正是需要的。但是,我也试图在表单文本字段中显示相同的数据,而这表现不同。我不得不为数据绑定编写一个转换器以避免 运行-time 错误,但结果与我的预期相反 - 它显示代码值而不是枚举。
一些代码来说明:
枚举类型:
public enum TaskType {
TASK_VIEW("00"), INTERACTIVE("01"), BATCH("02"), FOLDER("07"), URL("08"), USER_DEFINED("11");
private String codeValue;
private TaskType(String codeValue) {
this.codeValue = codeValue;
}
public String getCodeValue() {
return codeValue;
}
public static TaskType fromCodeValue(String value) {
switch (value) {
case "00":
return TASK_VIEW;
case "01":
return INTERACTIVE;
case "02":
return BATCH;
case "07":
return FOLDER;
case "08":
return URL;
case "11":
return USER_DEFINED;
default:
return null;
}
}
}
实体class:
@Entity
public class TaskMaster extends AbstractEntity {
private TaskType type;
// other fields
public TaskType getType() {
return type;
}
public void setType(TaskType type) {
this.type = type;
}
// other methods
}
数据库字段和枚举类型之间的转换器:
@Converter(autoApply = true)
public class TaskTypeConverter implements AttributeConverter<TaskType, String> {
@Override
public String convertToDatabaseColumn(TaskType type) {
if (type != null) {
return type.getCodeValue();
} else {
return null;
}
}
@Override
public TaskType convertToEntityAttribute(String dbData) {
if (dbData != null) {
return TaskType.fromCodeValue(dbData);
} else {
return null;
}
}
}
网格视图class:
public class TaskMasterListView extends VerticalLayout {
private Grid<TaskMaster> grid = new Grid<>(TaskMaster.class);
private TaskMasterService taskService;
public TaskMasterListView(TaskMasterService taskService) {
this.taskService = taskService;
...
}
@PostConstruct
public void init() {
List<TaskMaster> items = taskService.findAll();
grid.setItems(items);
}
private void configureGrid() {
grid.addClassName("tasks-grid");
grid.setColumns("internalTaskID", "taskID", "name", "type", "objectName", "version",
"formName");
grid.getColumns().forEach(col -> col.setAutoWidth(true));
}
...
}
详细信息视图(显示不正确的地方):
public class TaskDetailView extends FormLayout {
private static final Logger logger = LoggerFactory.getLogger(TaskDetailView.class);
private TextField type;
// other GUI objects
private Binder<TaskMaster> binder;
public TaskDetailView() {
configureView();
bindData();
}
public void loadTask(TaskTreeView.TaskSelectionEvent event) {
if (event.getSelected() != null) {
binder.setBean(event.getSelected());
}
}
private void bindData() {
binder = new Binder<>(TaskMaster.class);
binder.setBean(new TaskMaster());
binder.forField(type).withConverter(new TaskTypeConverter()).bind("type");
// other bindings
}
private static class TaskTypeConverter implements Converter<String, TaskType> {
@Override
public Result<TaskType> convertToModel(String value, ValueContext context) {
logger.info("convertToModel: value={}", value);
return Result.ok(TaskType.fromCodeValue(value));
}
@Override
public String convertToPresentation(TaskType value, ValueContext context) {
if (value != null) {
logger.info("convertToPresentation: value={}", value.toString());
return value.getCodeValue();
} else {
logger.info("convertToPresentation: null");
return "";
}
}
}
}
因此,举个例子,如果在网格中显示类型为 07
的实体,它会显示 FOLDER
,这就是我想要的。但是,当我在文本字段中显示类型显示的同一对象时,它显示 07
而不是 FOLDER
。
知道这里发生了什么吗?这似乎与我需要的相反。
您的 static class TaskTypeConverter
用于由活页夹从 TaskType.FOLDER
转换。现在让我们看看您的 convertToPresentation()
做了什么:它调用 value.getCodeValue()
所以您的 TextField 自然充满了 07
。
但是,您想要 return 枚举名称,因此您需要调用固有的枚举方法 value.name()
,反之亦然,在 convertToModel()
中调用 TaskType.valueOf(value)
。调用 valueOf()
!
时不要忘记捕获 IllegalArgumentException
和 NPE
最好不要使用 .name()
,而是使用一个友好的名称 f.e。您可以在枚举中保存的“文件夹”。
但是,您可能应该使用 Select<TaskType>
或 ComboBox<TaskType>
让用户从预定义的一组值(即来自枚举)而不是 TextField select。
通过 setItemLabelGenerator()
或渲染器设置友好名称(如果您需要自定义的不仅仅是文本)。
我有一条信息作为字符串代码值存储在数据库中table。我定义了一个枚举以使代码易于阅读。实体 class 使用枚举定义字段。
当我在 Vaadin 网格中显示数据时,它显示枚举值,这正是需要的。但是,我也试图在表单文本字段中显示相同的数据,而这表现不同。我不得不为数据绑定编写一个转换器以避免 运行-time 错误,但结果与我的预期相反 - 它显示代码值而不是枚举。
一些代码来说明:
枚举类型:
public enum TaskType {
TASK_VIEW("00"), INTERACTIVE("01"), BATCH("02"), FOLDER("07"), URL("08"), USER_DEFINED("11");
private String codeValue;
private TaskType(String codeValue) {
this.codeValue = codeValue;
}
public String getCodeValue() {
return codeValue;
}
public static TaskType fromCodeValue(String value) {
switch (value) {
case "00":
return TASK_VIEW;
case "01":
return INTERACTIVE;
case "02":
return BATCH;
case "07":
return FOLDER;
case "08":
return URL;
case "11":
return USER_DEFINED;
default:
return null;
}
}
}
实体class:
@Entity
public class TaskMaster extends AbstractEntity {
private TaskType type;
// other fields
public TaskType getType() {
return type;
}
public void setType(TaskType type) {
this.type = type;
}
// other methods
}
数据库字段和枚举类型之间的转换器:
@Converter(autoApply = true)
public class TaskTypeConverter implements AttributeConverter<TaskType, String> {
@Override
public String convertToDatabaseColumn(TaskType type) {
if (type != null) {
return type.getCodeValue();
} else {
return null;
}
}
@Override
public TaskType convertToEntityAttribute(String dbData) {
if (dbData != null) {
return TaskType.fromCodeValue(dbData);
} else {
return null;
}
}
}
网格视图class:
public class TaskMasterListView extends VerticalLayout {
private Grid<TaskMaster> grid = new Grid<>(TaskMaster.class);
private TaskMasterService taskService;
public TaskMasterListView(TaskMasterService taskService) {
this.taskService = taskService;
...
}
@PostConstruct
public void init() {
List<TaskMaster> items = taskService.findAll();
grid.setItems(items);
}
private void configureGrid() {
grid.addClassName("tasks-grid");
grid.setColumns("internalTaskID", "taskID", "name", "type", "objectName", "version",
"formName");
grid.getColumns().forEach(col -> col.setAutoWidth(true));
}
...
}
详细信息视图(显示不正确的地方):
public class TaskDetailView extends FormLayout {
private static final Logger logger = LoggerFactory.getLogger(TaskDetailView.class);
private TextField type;
// other GUI objects
private Binder<TaskMaster> binder;
public TaskDetailView() {
configureView();
bindData();
}
public void loadTask(TaskTreeView.TaskSelectionEvent event) {
if (event.getSelected() != null) {
binder.setBean(event.getSelected());
}
}
private void bindData() {
binder = new Binder<>(TaskMaster.class);
binder.setBean(new TaskMaster());
binder.forField(type).withConverter(new TaskTypeConverter()).bind("type");
// other bindings
}
private static class TaskTypeConverter implements Converter<String, TaskType> {
@Override
public Result<TaskType> convertToModel(String value, ValueContext context) {
logger.info("convertToModel: value={}", value);
return Result.ok(TaskType.fromCodeValue(value));
}
@Override
public String convertToPresentation(TaskType value, ValueContext context) {
if (value != null) {
logger.info("convertToPresentation: value={}", value.toString());
return value.getCodeValue();
} else {
logger.info("convertToPresentation: null");
return "";
}
}
}
}
因此,举个例子,如果在网格中显示类型为 07
的实体,它会显示 FOLDER
,这就是我想要的。但是,当我在文本字段中显示类型显示的同一对象时,它显示 07
而不是 FOLDER
。
知道这里发生了什么吗?这似乎与我需要的相反。
您的 static class TaskTypeConverter
用于由活页夹从 TaskType.FOLDER
转换。现在让我们看看您的 convertToPresentation()
做了什么:它调用 value.getCodeValue()
所以您的 TextField 自然充满了 07
。
但是,您想要 return 枚举名称,因此您需要调用固有的枚举方法 value.name()
,反之亦然,在 convertToModel()
中调用 TaskType.valueOf(value)
。调用 valueOf()
!
IllegalArgumentException
和 NPE
最好不要使用 .name()
,而是使用一个友好的名称 f.e。您可以在枚举中保存的“文件夹”。
但是,您可能应该使用 Select<TaskType>
或 ComboBox<TaskType>
让用户从预定义的一组值(即来自枚举)而不是 TextField select。
通过 setItemLabelGenerator()
或渲染器设置友好名称(如果您需要自定义的不仅仅是文本)。