Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
144 views
in Technique[技术] by (71.8m points)

java - Vaadin 14 - Text field not displaying enumeration correctly

I have a piece of information that is stored in a database table as a string code value. I have defined an enum to make the code human-readable. An entity class defines the field with the enum.

When I display the data in a Vaadin grid, it displays the enumeration value, which is what is needed. However, I am also trying to display the same data in a form text field, and this behaves differently. I had to write a converter for the data binding to avoid a run-time error, but the result is the opposite of what I expect - it shows the code value instead of the enumeration.

Some code to illustrate:

The enumeration type:

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;
    }
  }
}

The entity 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
}

A converter between database field and enum type:

@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;
    }
  }
}

The grid view 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));
  }

  ...
}

The details view (where it displays incorrectly):

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 "";
      }
    }
  }
}

So, as an example, if an entity with type = 07 is displayed in the grid, it shows FOLDER, which is what I want. But, when I display the same object where the type is shown in a text field, it shows 07 instead of FOLDER.

Any idea what's going on here? It seems to be doing the opposite of what I need.

question from:https://stackoverflow.com/questions/65860095/vaadin-14-text-field-not-displaying-enumeration-correctly

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your static class TaskTypeConverter is used to convert from TaskType.FOLDER by the binder. Now let's see what your convertToPresentation() does: it calls value.getCodeValue() so of course your TextField is filled with 07. However, you want to return the enum name, so you need to call the inherent enum method value.name() and vice-versa call TaskType.valueOf(value) inside convertToModel(). Don't forget to catch IllegalArgumentException and NPE when calling valueOf()!


A good idea would be not to use .name() but a friendly name f.e. "Folder" which you can hold in your enum.


However, you should probably use a Select<TaskType> or ComboBox<TaskType> for the users to select from a predefined set of values i.e. from an enum, instead of a TextField.

Set the friendly name through setItemLabelGenerator() or a Renderer if you need to customize it more than just text.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...