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
}
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));
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With