Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate Integers from a TextField in a table with a wrapper

Tags:

vaadin

vaadin7

I have a table where I'm using createField() to create the fields. In editing mode, users are able to input text into the fields.

One of the columns in this table should only allow Integers and therefore I am using an IntegerRangeValidator.

The validation should be dynamic (as-you-type) and if the input is validated false, a little red exclamation mark should be shown and the tooltip should say something like "Only Integers allowed!". To be able to show these exclamation marks and have this dynamic validation, I needed to use a wrapper that listens to textChanges every 200ms.

The problem is that the TextField is returning a String, so the validator interprets everything as Strings, even if the user has typed an integer into the field.

In Vaadin 7 - How do I validate Integers from a TextField that is inside a table when the validation is executed in an overriden textChange-method in a wrapper?

The createField-method:

@Override
public Field<?> createField(Container container, Object itemId, Object propertyId, com.vaadin.ui.Component uiContext) {

    TextField tField = null;

    tField = (TextField) super.createField(container, itemId, propertyId, uiContext);
    tField.setBuffered(true);
    addFieldListeners(tField);

    if (propertyId.equals("age") {
        tField.setRequired(true);
        tField.setRequiredError("This field is required!");
        // tField.setConverter(new StringToIntegerConverter()); <-- I also tried this, without success
        tField.addValidator(new IntegerRangeValidator("Only Integers allowed!", 1, 150));
        @SuppressWarnings({ "unchecked", "rawtypes" })
        TableDataValidatingWrapper<TextField> wField = new TableDataValidatingWrapper(tField);
        return wField;
    } else {
        return null;
    }
}

The wrapper:

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

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

    public TableDataValidatingWrapper(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.setCaption("");

            textField.addTextChangeListener(new FieldEvents.TextChangeListener() {

                private static final long serialVersionUID = 1L;

                @Override
                public void textChange(FieldEvents.TextChangeEvent event) {
                    try {
                        textField.setValue(event.getText());
                        textField.validate();
                    } catch (EmptyValueException e) {
                        System.out.println("Caught exception " + e);
                    } catch (InvalidValueException e) {
                        System.out.println("Caught exception " + e);
                    } catch (Exception e) {
                        System.out.println("Caught unknown exception " + e);
                    }
                }
            });
        }
    }

    // ... some other overridden methods
}
like image 352
Roger Avatar asked Nov 06 '13 15:11

Roger


2 Answers

You can add an Converter to your TextField that converts Strings into Integers:

tField.setConverter(new StringToIntegerConverter());
tField.addValidator(new IntegerRangeValidator("Only Integers allowed!", 1, 150));
like image 99
Claas Wilke Avatar answered Sep 22 '22 18:09

Claas Wilke


I solved this by using my own CustomIntegerRangeValidator for the String fields that should be validated as Integers, like so:

public class CustomIntegerRangeValidator extends AbstractValidator<String> {

    private static final long serialVersionUID = 1L;

    private IntegerRangeValidator integerRangeValidator;

    public CustomIntegerRangeValidator(String errorMessage, Integer minValue, Integer maxValue) {
        super(errorMessage);
        this.integerRangeValidator = new IntegerRangeValidator(errorMessage, minValue, maxValue);
    }

    @Override
    protected boolean isValidValue(String value) {
        try {
            Integer result = Integer.parseInt(value);
            integerRangeValidator.validate(result);
            return true;
        } catch (NumberFormatException nfe) {
            // TODO: handle exception
            System.out.println("Cannot be parsed as Integer: " + nfe);
            return false;
        } catch (Exception e) {
            // TODO: handle exception
            System.out.println("Unknown exception: " + e);
            return false;
        }

    }

    @Override
    public Class<String> getType() {
        return String.class;
    }

}
like image 23
Roger Avatar answered Sep 21 '22 18:09

Roger