3

当我进入表的编辑模式时,我希望在用户超出任何验证约束的范围时立即显示数据验证感叹号图标 (!)。

首先,有几点注意事项:

  • 我正在使用 Vaadin 7,所以 Bean Validation 插件很遗憾无法工作。
  • 数据验证按预期工作。

现在,我有一个完美的工作表,我正在使用 BeanItemContainer 将我的 Person bean 保存在里面。

表和 TableFieldFactory 的代码如下所示:

table.setContainerDataSource(buildContainer());
table.setTableFieldFactory(new TableFieldFactory() {
    @Override
    public Field createField(Container container, Object itemId, Object propertyId, Component uiContext) {
        TextField field = (TextField) DefaultFieldFactory.get().createField(container, itemId, propertyId,
                uiContext);
        field.setImmediate(true);
        if (propertyId.equals("firstName")) {
            field.addValidator(new BeanValidator(Person.class, "firstName"));
        }
        return field;
    }
});

Person bean 如下所示:

public class Person {

    @Size(min = 5, max = 50)
    private String firstName;

    ... setters + getters...
}

问题是,当我在 firstName 字段中输入内容然后按回车键或模糊/取消聚焦该字段时,不会显示任何错误指示。我必须将鼠标悬停在该字段上才能看到有问题。

我的问题是两个折叠...

  1. 字段无效时如何显示感叹号图标?(这适用于不在表格中的普通 TextField)
  2. 有没有办法从无效字段(显示图标)获得即时响应(即在您键入 5 个字符后立即响应,而无需按回车键或模糊/取消焦点相关字段)。

如果我能回答这两个问题就太好了!=)

提前致谢!

4

1 回答 1

3
  1. 标题、必需指示符(红色星号)和 - 最重要的是 - 错误指示符(感叹号)实际上是由包含组件的布局提供的,而不是组件本身。当可编辑组件显示在表格中时,它们显示时没有布局 - 这就是不显示错误指示器的原因。

    如果我试图使这个圆圈平方,我会考虑创建一个 CustomField 作为可编辑字段的包装器 - 当包装/委托字段变得无效时,在该 CustomField 中显示一个错误指示符。我没有尝试过——我根本没有在表格中使用过可编辑字段——但应该很容易做到。

  2. 在 FieldFactory 的字段中添加一个TextChangeListener,并在监听器中调用 field.validate()。但是请注意,该 field.getValue() 值通常在模糊/取消聚焦之前不会更改,因此验证器将验证旧值 - 除非您在侦听器中执行 field.setValue(event.getText())。有关更多详细信息,请参阅Vaadin 论坛上的此帖子。

这就是我对验证包装器的意思——没有尝试过使用它。您会看到 initComponent 仅返回 FormLayout 中的字段,它应该为您提供您正在寻找的图标。(您可能需要将 ValidatingWrapper 中的更多方法委托给委托,而不是我所拥有的 - 但快速浏览表明这可能就足够了。)

然后将字段包装在 tableFieldFactory 中(第二个代码块)

public class ValidatingWrapper<T> extends CustomField<T> {

  private static final long serialVersionUID = 9208404294767862319L;
  protected Field<T> delegate;

  public ValidatingWrapper(final Field<T> delegate) {
    this.delegate = delegate;

    if (delegate instanceof TextField) {
      final TextField textField = (TextField) delegate;
      textField.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.TIMEOUT);
      textField.setTextChangeTimeout(200);

      textField.addTextChangeListener(new FieldEvents.TextChangeListener() {
        @Override
        public void textChange(FieldEvents.TextChangeEvent event) {
          textField.setValue(event.getText());
          textField.validate();
        }
      });
    }
  }

  @Override
  public Class<? extends T> getType() {
    return delegate.getType();
  }

  @Override
  protected Component initContent() {
    return new FormLayout(delegate);
  }


  @Override
  public Property getPropertyDataSource() {
    return delegate.getPropertyDataSource();
  }

  @Override
  public void setPropertyDataSource(Property newDataSource) {
    delegate.setPropertyDataSource(newDataSource);
  }

}
   

table.setContainerDataSource(buildContainer());
table.setTableFieldFactory(new TableFieldFactory() {
  @Override
  public Field createField(Container container, Object itemId, Object propertyId, Component uiContext) {
    TextField field = (TextField) DefaultFieldFactory.get().createField(container, itemId, propertyId,
        uiContext);
    field.setImmediate(true);
    if (propertyId.equals("firstName")) {
      field.addValidator(new BeanValidator(Person.class, "firstName"));
    }
    return ValidatingWrapper(field);
  }
});
于 2013-07-31T08:13:51.650 回答