【问题标题】:Vaadin 14 - How to allow null values in form validationVaadin 14 - 如何在表单验证中允许空值
【发布时间】:2021-02-05 13:51:47
【问题描述】:

我正在编写的应用程序的一部分是任务的“编辑器”表单。某些任务实体字段可以为空,例如:完成日期。

我使用Binder 将实体字段绑定到编辑器字段并执行验证。我遇到了验证失败的问题,因为项目(如完成日期)为空。这可以为空。但是,该字段被标记为“value null”并且实体未保存。

有没有办法标记本质上是可选字段以便允许空值?当然,如果输入了值,则需要对其进行验证。

Task.java(实体)

@Entity
public class Task extends AbstractEntity {

  ...
  // These are optional fields.
  private Long           dateDue;
  private Long           dateStarted;
  private Long           dateCompleted;
  ...
}

EditTaskForm.java

public class EditTaskForm extends VerticalLayout {

  private DatePicker                  dateDue;
  private DatePicker                  dateStarted;
  private DatePicker                  dateCompleted;
  ...
  
  private void bindData() {
    binder = new Binder<>(Task.class);

    ...
    binder.forField(dateDue)
      .withConverter(new LocalDateToLongConverter())
      .bind("dateDue");

    binder.forField(dateStarted)
      .withConverter(new LocalDateToLongConverter())
      .bind("dateStarted");

    binder.forField(dateCompleted)
      .withConverter(new LocalDateToLongConverter())
      .bind("dateCompleted");
    
    binder.withValidator(new TaskValidator());
  }

  private void validateAndSave() {
    try {
      binder.writeBean(task);
      fireEvent(new SaveEvent(this, task));
    } catch (ValidationException e) {
      logger.error("field validation errors:");
      e.getFieldValidationErrors().forEach(er -> {
        logger.error("status: {}", er.getStatus());
        logger.error("message: {}", er.getMessage().get());

        logger.error("field: {}", er.getField().getValue());
      });

      logger.error("bean validation errors:");
      e.getBeanValidationErrors().forEach(er -> {
        logger.error(er.getErrorMessage());
      });
    }
  }
  
  ...
}

如果我运行应用程序,创建一个新任务,不为任何这些可选字段指定值并尝试验证和保存,表单上的每个字段都会被标记为消息“value null”并突出显示。

更新

原来“空值”来自LocalDateToLongConverter。这是(注意注释掉的代码):

public class LocalDateToLongConverter implements Converter<LocalDate, Long> {

  private ZoneId            zoneId;

  public LocalDateToLongConverter(ZoneId zoneId) {
    this.zoneId = Objects.requireNonNull(zoneId, "Zone id cannot be null");
  }

  public LocalDateToLongConverter() {
    this(ZoneId.systemDefault());
  }

  @Override
  public Result<Long> convertToModel(LocalDate value, ValueContext context) {
    if (value != null) {
      return Result.ok(Date.from(value.atStartOfDay(zoneId).toInstant()).getTime());
    } else {
      return Result.ok(null);
      // return Result.error("value null");
    }
  }

  @Override
  public LocalDate convertToPresentation(Long value, ValueContext context) {
    if (value != null) {
      return Instant.ofEpochMilli(value).atZone(zoneId).toLocalDate();
    } else {
      return null;
    }
  }

}

【问题讨论】:

  • 请添加您尝试过的代码以及失败的原因(例如错误、堆栈跟踪、日志等),以便我们对其进行改进。
  • 为什么我的投票被否决了?就我而言,如果有人要否决别人的帖子,他们应该被要求提供理由。

标签: validation vaadin


【解决方案1】:

虽然描述有点不清楚,代码示例也不够全面,我无法尝试,但我仍然非常怀疑会发生什么。

文本“value null”并非源自 Binder 本身或 Vaadin 的任何其他部分。相反,它很可能是由自定义 LocalDateToLongConverter 实现产生的。因此,我建议您查看其实现,看看是否是导致字段被标记为无效的原因。

【讨论】:

  • 你是对的。我已经用我发现的内容更新了帖子。
猜你喜欢
  • 2011-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-29
相关资源
最近更新 更多