【问题标题】:How to determine if a DateField is valid in Vaadin 8如何确定 DateField 在 Vaadin 8 中是否有效
【发布时间】:2017-10-06 04:13:07
【问题描述】:

我有:

DateField dateField = new DateField("Date");
Button submitButton = new Button("Submit");
submitButton.addClickListener(click -> handleClickListener());

如果DateField 中存在验证错误,我想阻止提交handleClickListener()。我知道我可以使用 Binder,然后使用 binder.validate(),但是这个表单没有支持对象,我只想要一个简单的表单。我该怎么做:

if(!dateField.isValid())
   // no further processing
else
   // process

我在DateField 中找不到任何允许检查输入值是否有效的代码。显然是in Vaadin 7 you could !dateField.validate() which would throw an exception,但现在似乎不再是这种情况了......

我也知道可以执行 dateField.isEmpty() 或测试 null 但这不起作用,因为不需要值。换句话说,它可以是空的,或者如果你输入一个值,那么它必须是一个有效的条目。

【问题讨论】:

  • 使用Binder (vaadin.com/api/8.0.1/com/vaadin/data/Binder.html) 怎么样? Binder 带有 validate()isValid() 等方法。
  • 有时 Binder 不起作用。例如我的表单后面可能没有 POJO 等,可能我只是在使用表单对标签进行快速计算,不想用任何东西支持它。

标签: java vaadin vaadin8


【解决方案1】:

这已经被问过好几次了,据我所知,没有活页夹是不可能添加验证器的。您可以查看this answer 以获得对该功能和共鸣的全面描述。

还有关于Vaadin forumgithub 的讨论,其中两个主要建议是使用活页夹,或手动调用验证器的值更改侦听器。但是,后一种解决方案似乎不起作用,我怀疑这是因为只有在实际值更改时才会触发值更改事件,当您键入无效的内容时可能不会发生这种情况,但我没有花太多时间调查。

latest suggestion on github 请求 binder.noBind() 方法来简化这些情况,但在实现之前,您可以使用类似于以下代码示例的内容。我也讨厌使用字段绑定值的想法,所以我采用了 no setterno getter 的概念:

public class DateFieldWithValidator extends VerticalLayout {

    public DateFieldWithValidator() {
        // date field with binder
        Binder<LocalDate> binder = new Binder<>();
        DateField dateField = new DateField("Date");
        binder.forField(dateField)
              .asRequired("Please select a date")
              .bind(No.getter(), No.setter());

        // validity status
        TextField validityField = new TextField("Status:", "N/A");
        validityField.setReadOnly(true);
        validityField.addStyleName(ValoTheme.TEXTFIELD_BORDERLESS);
        validityField.setWidth("100%");

        // submit button
        Button submitButton = new Button("Submit");
        submitButton.addClickListener(event -> {
            BinderValidationStatus<LocalDate> status = binder.validate();
            if (status.isOk()) {
                validityField.setValue("OK: " + dateField.getValue().toString());
            } else {
                validityField.setValue("KO: " + status.getValidationErrors().stream().map(ValidationResult::getErrorMessage).collect(Collectors.joining(",")));
            }
        });

        addComponents(dateField, submitButton, validityField);
    }

    // convenience empty getter and setter implementation for better readability
    public static class No {
        public static <SOURCE, TARGET> ValueProvider<SOURCE, TARGET> getter() {
            return source -> null;
        }

        public static <BEAN, FIELDVALUE> Setter<BEAN, FIELDVALUE> setter() {
            return (bean, fieldValue) -> {
                //no op
            };
        }
    }
}

结果:


后期更新:

我一直在考虑更多,如果可以接受,如果值为 null 或出现无效值的解析错误,您可以禁用提交按钮。这可以通过ValueChangeListenerErrorHandler 轻松实现,如下所示。

或者,您可以将异常消息保存在变量中,当您单击按钮时,检查是否有错误消息或值为空,按此顺序,因为如果输入无效日期,该字段的值将设置为空。

public class DateFieldWithValidator extends VerticalLayout {
    public DateFieldWithValidator() {
        DateField dateField = new DateField("Date");
        Button submitButton = new Button("Submit");
        submitButton.setEnabled(false);
        submitButton.addClickListener(event -> Notification.show("Selected date: " + dateField.getValue()));
        dateField.setRequiredIndicatorVisible(true);
        dateField.setErrorHandler(event -> submitButton.setEnabled(false));
        dateField.addValueChangeListener(event -> submitButton.setEnabled(event.getValue() != null));
        addComponents(dateField, submitButton);
    }
}

结果:

【讨论】:

  • 这与我所做的非常接近。您基本上创建了一个假 POJO(或类似的东西)来与 Binder 绑定,然后在单击提交按钮时使用活页夹的验证。
  • @StephaneGrenier 是的,这就是这个想法,至少目前是这样......
  • @StephaneGrenier 第二种方法怎么样?
【解决方案2】:

即使您声明不想使用支持对象,我还是建议使用Binder。我认为@Morfic 提供的No 类非常好(我倾向于在许多验证实现中重用它)。

所以我要做的是在你的活页夹上添加一个addStatusChangeListener 并启用/禁用那里的按钮:

binder.addStatusChangeListener(event -> {
            if (event.hasValidationErrors()) {
                submitButton.setEnabled(false);
            } else {
                submitButton.setEnabled(true);
            }
        });

省略了 Binder 对象的实例化,因为 @Morfic 在他的回答中已经提供了一个很好的例子。

我建议使用Binder 的原因是因为Vaadin suggests to use it for validation,您不需要很难维护值更改侦听器,并且如果以后需要,您可以轻松地使用新的Validators 扩展您的绑定。也许你会想在某一时刻将字段绑定到一个对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-11
    • 2012-06-08
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    • 2012-11-27
    • 1970-01-01
    相关资源
    最近更新 更多