【问题标题】:How to create a real time validator on a text field in Vaadin?如何在 Vaadin 的文本字段上创建实时验证器?
【发布时间】:2015-01-16 12:04:32
【问题描述】:

我目前正在使用 Vaadin 7.3+,并希望在用户实时输入时在文本字段中进行验证。

这是我迄今为止尝试过的:

textField.setTextChangeEventMode(TextChangeEventMode.LAZY);
textField.setNullRepresentation("");

textField.addTextChangeListener(new FieldEvents.TextChangeListener() {
    @Override
    public void textChange(FieldEvents.TextChangeEvent event) {
        for (Validator v : textField.getValidators()) {
            try {
                v.validate(event.getText());
            } catch (InvalidValueException e) {
                log.warn("validation error: " + e.getMessage() + " and value was: {}", event.getText());
            }
        }
    }
});

问题在于,尽管所有验证器都在执行并且验证正在完成,但直到焦点离开该字段,即用户按 Enter 或单击其他位置时,才会呈现红色错误指示器。我尝试添加 textField.markAsDirty 但这不起作用。有谁知道这个问题的解决方案?或者在文本字段上创建实时验证器的一般更好的解决方案?

提前感谢您的时间和意见:-)

【问题讨论】:

    标签: java vaadin vaadin7


    【解决方案1】:

    Vaadin 核心中的验证器并非设计为在键入时工作,这对于 RIA 框架来说是一种耻辱。这有望在即将发布的版本中得到修复。让它在今天与核心组件一起正常工作有点棘手,但可行。如果您的服务器和客户端之间存在一些延迟,您自己的解决方案可能存在一些 UX 问题 - 如果用户在执行验证器时再次开始重新输入,则光标可能会跳到意外的位置。我在Viritin add-on 做了很多工作。通过将其 AbstractForm(或原始 MBeanFieldGroup)与 MTextField 一起使用,这应该可以很好地工作并且无需任何配置。您可以尝试使用该解决方案,例如this example.

    【讨论】:

      【解决方案2】:

      这里的问题是,事件发送文本,但实际上并没有修改输入的值。解决这个问题的最简单方法是设置值。例如

      addTextChangeListener(new FieldEvents.TextChangeListener() {
          @Override
          void textChange(FieldEvents.TextChangeEvent event) {
              final textField = event.source as TextField
              textField.value = event.text
          }
      })
      

      这只会触发字段以及验证器的更改,所有这些都将按预期传递给客户端。

      编辑

      正如您在 cmets 中所述,应保留光标 pos。您可以使用所需的任何方式验证事件中的文本。这里的关键是,只需设置字段的componentError 即可在字段的最后一行得到错误。

      @Override
      void textChange(FieldEvents.TextChangeEvent event) {
          final tf = event.source as TextField
          try {
              tf.validate(event.text) // this works in groovy!  not java.
              tf.setComponentError(null)
          }
          catch (InvalidValueException e) {
              tf.setComponentError(new SystemError(e))
          }
      }
      

      【讨论】:

      • 您的解决方案的一个问题是设置字段的值会导致光标位置跳到文本的末尾(至少在 Safari 和 Chrome 中)。
      • 当我输入文字时,它不在那里吗?
      • 如果您正在编辑字段,则不会。例如在需要编辑一些属性的配置工具中:-)
      • 那么您最好使用客户端验证。参见例如vaadin.com/directory#addon/csvalidationvaadin.com/wiki/-/wiki/Main/Client%20Side%20Validation。上次我想处理我放弃的客户端焦点和服务器端代码。
      • 很遗憾,感谢您的解决方案,因为我正在使用 BeanValidator,因此我在此解决方案中丢失了向用户发送的错误消息(最初是通过 @NotNull(message="This field is required" 定义的)。令人惊讶的是,最直接的解决方法和最愚蠢的解决方案似乎有效。请参阅下面的答案。
      【解决方案3】:

      这种直截了当的解决方法似乎工作正常,尽管它很不优雅。

      textField.setTextChangeEventMode(TextChangeEventMode.LAZY);
      textField.setNullRepresentation("");
      
      textField.addTextChangeListener(new FieldEvents.TextChangeListener() {
          @Override
          public void textChange(FieldEvents.TextChangeEvent event) {
              try {
                  textField.setValue(event.getText());
      
                  // workaround cursor position problem
                  textField.setCursorPosition(event.getCursorPosition());
      
                  textField.validate();
                  } catch (InvalidValueException e) {
                      log.warn("validation error: " + e.getMessage() + " and value was: {}", delegate.getValue());
                  }
          }
      });
      

      【讨论】:

      • 这是一个糟糕的解决方案,即使使用光标位置解决方法,当客户端和服务器之间的连接速度很慢时,它仍然会导致 UX 问题。检查@cfirck 答案
      【解决方案4】:

      Take a look 在 Vaadin 文档中。如果我说对了,将字段设置为立即模式应该没问题。有时建议允许空值以避免不必要的警告。

      TextField field = new TextField("Name");
       field.addValidator(new StringLengthValidator(
      "The name must be 1-10 letters (was {0})",
      1, 10, true));
      field.setImmediate(true);
      field.setNullRepresentation("");
      field.setNullSettingAllowed(true);
      

      【讨论】:

      • @mjjaniec 也许这个example 会帮助你。虽然它与验证无关,但它很好地展示了 textchange 监听器的使用。
      猜你喜欢
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多