How to use the GWT editor framework for validation?

倖福魔咒の 提交于 2019-11-30 04:47:49

Annotate you beans with contstrants (see Person.java)

public class Person {
  @Size(min = 4)
  private String name;
}

Use the standard validation bootstrap to get a Validator on the client and validate your object (see ValidationView.java)

Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<Person>> violations = validator.validate(person);

Follow this pattern to create a Validator for the objects you want to validate on the client. (see SampleValidatorFactory.java)

public final class SampleValidatorFactory extends AbstractGwtValidatorFactory {

  /**
   * Validator marker for the Validation Sample project. Only the classes listed
   * in the {@link GwtValidation} annotation can be validated.
   */
  @GwtValidation(value = Person.class,
      groups = {Default.class, ClientGroup.class})
  public interface GwtValidator extends Validator {
  }

  @Override
  public AbstractGwtValidator createValidator() {
    return GWT.create(GwtValidator.class);
  }
}

Include the module for your Validation Provider. Add replace-with tag in your gwt modle file telling GWT to use the Validator you just defined (see Validation.gwt.xml)

<inherits name="org.hibernate.validator.HibernateValidator" />
<replace-with
    class="com.google.gwt.sample.validation.client.SampleValidatorFactory">
    <when-type-is class="javax.validation.ValidatorFactory" />
</replace-with>

Source

I have done something similar to this by adding an additional DriverWrapper class that takes the existing Driver and Validator and adds a flush method that first delegates to the underlying Driver flush and then calls the Validator. Any errors returned are then added to the Editors using a new visitor, similar to the way the existing Flusher works. This means the existing decorators that display the errors next to the fields continue to work.

/**
 * Wraps a Driver and provides validation using gwt-validation (JSR 303).
 * When calling flush, this will use the provided IValidator to validate the data
 * and use the InvalidConstraintValidationVisitor to add the errors to the delegates.
 * @see InvalidConstraintValidationVisitor
 * @param <T> the data type for the editor
 * @param <D> the driver type
 */
public class ValidationDriverWrapper<T extends IsValidatable<T>, D extends EditorDriver<T>> {
private IValidator<T> validator;
private D driver;

/**
 * Constructor, both parameters are required.
 * @param driver The driver to use to flush the underlying data.
 * @param validator The validator to use to validate the data.
 */
public ValidationDriverWrapper(D driver, IValidator<T> validator) {
    this.validator = validator;
    this.driver = driver;
}

/**
 * Flushes the underlying Driver and then calls the validation on the underlying Validator, cascading errors as EditorErrors
 * onto the delegates, using InvalidContraintValidationVisitor.
 */
public void flush()
{
    T data = driver.flush();
    Set<InvalidConstraint<T>> errors = validator.validate(data);
    Set<InvalidConstraint<T>> extraErrors = data.validate();
    if(extraErrors != null && !extraErrors.isEmpty())
    {
        errors.addAll(extraErrors);
    }
    driver.accept(new InvalidConstraintValidationVisitor<T>(errors));
}

I've got exaclty the same problem.

The documentation is not clear about it.

What I'm currently doing is to recreate some widgets by extending them with widget I want to copy. After it I implement LeafValueEditor and HasEditorDelegate to override getValue().

In getValue(), use your validator and call if needed yourDelegate.recordError().

Something like this: a little integer box which check that value is not greater than 10.

public class IntegerField extends ValueBox<Integer> implements LeafValueEditor<Integer>, HasEditorDelegate<Integer>
{
private EditorDelegate<Integer> delegate;

public IntegerField()
{
    super(Document.get().createTextInputElement(), IntegerRenderer.instance(), IntegerParser.instance());

    setStyleName("gwt-TextBox");

}

@Override
public Integer getValue()
{
    Integer value = super.getValue();

    if (value > 10)
    {
        delegate.recordError("too big integer !", value, null);
    }

    return value;
}

@Override
public void setValue(Integer value)
{
    super.setValue(value);
}

@Override
public void setDelegate(EditorDelegate<Integer> delegate)
{
    this.delegate = delegate;
}
}

The best approach is to simply add custom verification to existing widgets and not override them but I don't know how to do it !

Validation doesn't exist in GWT yet, it's coming in the next release AFAIK. The current support for validation in GWT is server side JSR-303 and client side JSR-303 support is coming soon. Therefore, you'll have to do the validation manually. If you follow the MVP model, I think this validation logic would live in your Presenter.

It's messy but to get the path of an Editor you could implement HasEditorDelegate (which will give you access to the delegate) and then cast the Delegate to AbstractEditorDelegate, which has a public String getPath() method.

I don't think it is possible to do external validation though; validation happens in the editor at the point that a value is read from the field (see ValueBoxEditor - this editor uses getDelegate().recordError to raise an error). One option I did consider was to use the AbstractEditorDelegate access to call flushErrors(List) and to create that list of EditorErrors myself. To do that you need to know each of your field paths; hardcoding them is hardly desirable, but I don't see a way of looking up the Field by the edited property or anything like that.

An alternative approach that might bear looking into is this submission for round trip validation using the requestfactory:

http://groups.google.com/group/google-web-toolkit-contributors/browse_thread/thread/5be0bda80547ca5a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!