如何在Vaadin中的文本字段上创建实时验证器?

时间:2015-01-16 12:04:32

标签: java vaadin vaadin7

我目前正在使用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());
            }
        }
    }
});

问题在于,虽然正在执行所有验证器并且正在进行验证,但是在焦点离开该字段之前不会呈现红色错误指示符,即用户点击进入或点击其他地方。我尝试添加textField.markAsDirty,但这不起作用。有谁知道这个问题的解决方案?或者更好的解决方案是在文本字段上创建实时验证器?

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

4 个答案:

答案 0 :(得分:2)

Vaadin核心的验证器不适合在打字时工作,这对于RIA框架来说是一种耻辱。希望在即将推出的版本中修复此问题。今天使用核心组件使其运行良好有点棘手,但可行。如果服务器和客户端之间存在一些延迟,您自己的解决方案可能会出现一些UX问题 - 如果用户在执行验证程序时再次重新键入,则游标可能会跳转到非预期的位置。我在Viritin add-on中已经做了很多工作。通过将其AbstractForm(或原始MBeanFieldGroup)与MTextField一起使用,这应该可以很好地工作,无需任何配置。您可以尝试使用例如this example

答案 1 :(得分:1)

这里的问题是,事件发送文本,但实际上并没有修改输入的值。解决这个问题最简单的方法就是设定价值。 e.g。

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

这只会触发字段和验证器的更改,并且所有内容都会按预期进入客户端。

修改

正如您在评论中所述,应保留光标位置。您可以使用您需要的任何方式验证事件中的文本。这里的关键点是,只需设置字段的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))
    }
}

答案 2 :(得分:1)

这个直接的解决方案似乎工作正常,虽然它非常不优雅。

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

答案 3 :(得分:0)

Vaadin文档中的

Take a look。如果我说得对,那么将你的领域设置为立即模式应该没问题。有时建议允许空值以避免不必要的警告。

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