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