I am using a Vaadin text field and I want to restrict it to support numbers only in it. I tried to override setValue()
and return without calling super. setValue()
if text is not a number. But it doesn't seems to be working. How can I correct this?
I am using Vaadin 7. And I think it doesn't support NumberField as well.

- 31,165
- 11
- 75
- 105

- 4,706
- 9
- 36
- 50
7 Answers
If I understand you question correct, you want to have a field that ignores all inputs that are not a number and not only mark the field as invalid. Vaadins architecture is designed that every field in the browser has its representation on the server. In my opinion the cleanest way to achieve this would be to have a browser field, that permits input of letters and other wrong characters. I couldn't find such a field in Vaadin 7. There seems to be an add-on for vaadin 6 called Number Field for that, but I didn't test it.
You have multiple options:
Port this add-on to vaadin 7 or ask the author to do it
Write your own field. Maybe extending VTextField and TextFieldConnector
Do everything on the server side and accept the delays and the traffic (IMHO ugly)
Since I think option 3 is not the way to go, I probably shouldn't show this code, but it's the quickest way to implement this.
public class IntegerField extends TextField implements TextChangeListener {
String lastValue;
public IntegerField() {
setImmediate(true);
setTextChangeEventMode(TextChangeEventMode.EAGER);
addTextChangeListener(this);
}
@Override
public void textChange(TextChangeEvent event) {
String text = event.getText();
try {
new Integer(text);
lastValue = text;
} catch (NumberFormatException e) {
setValue(lastValue);
}
}
}

- 5,179
- 10
- 35
- 56

- 2,427
- 4
- 26
- 42
-
thanks dude. It works fine. I added some null check and empty check and handled them. – Sanjaya Liyanage Jun 24 '13 at 10:30
-
Working but when typing lots of characters quickly you can still enter unwanted content – Eyal Sep 11 '14 at 16:25
-
1Its generally considered bad practice to use exceptions for control flow. See http://c2.com/cgi/wiki?DontUseExceptionsForFlowControl, http://programmers.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why or http://stackoverflow.com/questions/729379/why-not-use-exceptions-as-regular-flow-of-control. – s.froehlich Dec 02 '14 at 13:59
-
1Thanks for the code Raffael, but it is important to said, that this is not the proper solution, cause to delays in comunication the value can accept wrongs values or deny valid values. – Diego Quirós Jul 15 '15 at 02:24
Vaadin 7 allows to extend their built in widgets (if you want to have more knowledge on this I really recommend this post) here is a solution which uses that mechanism.
It is composed of two classes: Connector and the Extension
The Extension
package com.infosystem.widgets.vaadin; import com.vaadin.server.AbstractClientConnector; import com.vaadin.server.AbstractExtension; import com.vaadin.ui.TextField; public class NumberField extends AbstractExtension { public static void extend(TextField field) { new NumberField().extend((AbstractClientConnector) field); } }
Connector:
package com.infosystem.widgets.vaadin.client.numberField; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyPressEvent; import com.google.gwt.event.dom.client.KeyPressHandler; import com.infosystem.widgets.vaadin.NumberField; import com.vaadin.client.ComponentConnector; import com.vaadin.client.ServerConnector; import com.vaadin.client.extensions.AbstractExtensionConnector; import com.vaadin.client.ui.VTextField; import com.vaadin.shared.ui.Connect; @Connect(NumberField.class) public class NumberFieldConnector extends AbstractExtensionConnector { private static final long serialVersionUID = -737765038361894693L; private VTextField textField; private KeyPressHandler keyPressHandler = new KeyPressHandler() { @Override public void onKeyPress(KeyPressEvent event) { if (textField.isReadOnly() || !textField.isEnabled()) { return; } int keyCode = event.getNativeEvent().getKeyCode(); switch (keyCode) { case KeyCodes.KEY_LEFT: case KeyCodes.KEY_RIGHT: case KeyCodes.KEY_BACKSPACE: case KeyCodes.KEY_DELETE: case KeyCodes.KEY_TAB: case KeyCodes.KEY_UP: case KeyCodes.KEY_DOWN: case KeyCodes.KEY_SHIFT: return; } if (!isValueValid(event)) { textField.cancelKey(); } } }; @Override protected void extend(ServerConnector target) { textField = (VTextField) ((ComponentConnector) target).getWidget(); textField.addKeyPressHandler(keyPressHandler); } private boolean isValueValid(KeyPressEvent event) { String newText = getFieldValueAsItWouldBeAfterKeyPress(event.getCharCode()); try { parseValue(newText); return true; } catch (Exception e) { return false; } } protected long parseValue(String value) { return Long.valueOf(value); } private String getFieldValueAsItWouldBeAfterKeyPress(char charCode) { int index = textField.getCursorPos(); String previousText = textField.getText(); StringBuffer buffer = new StringBuffer(); buffer.append(previousText.substring(0, index)); buffer.append(charCode); if (textField.getSelectionLength() > 0) { buffer.append(previousText.substring(index + textField.getSelectionLength(), previousText.length())); } else { buffer.append(previousText.substring(index, previousText.length())); } return buffer.toString(); } }
To use the code above you need to add it to your current widget set. Afterwards the use of this is as follows:
TextField field = new TextField();
NumberField.extend(field);

- 5,179
- 10
- 35
- 56

- 121
- 1
- 3
-
1To add it to the widgetset, the Connector class should be in a folder called "client" at the same level as the custom widgetset file (MyWigetSet.gwt.xml for example). To use a custom widgetset, this must be declared as an init-param in the servlet. – enkara Feb 26 '16 at 13:19
In Vaadin 7, you can use a TextField and set a validator to allow only numbers:
TextField textField;
textField.addValidator(new RegexpValidator("[-]?[0-9]*\\.?,?[0-9]+"), "This is not a number!");
Change the regex to fit your needs. Remember that still is handling Strings and therefore you still need to convert the returning value of the TextField:
Long.parseLong(textField.getValue())

- 1,442
- 4
- 29
- 50
With Vaadin 8, you can use Binder
:
Binder<YouBean> binder = new Binder<>();
binder.forField(textField)
.withConverter(new StringToIntegerConverter("Must be Integer"))
.bind(YouBean::getter, YouBean::setter);
binder.setBean(bean); //optional

- 5,179
- 10
- 35
- 56
-
I migrated from the TextField from vaadin 7 to 8, and it worked using this: Binder
without the 'bind' call. There is no comment on migrating this from 7 to 8 and your comment should be in the official doc. – Sebastian D'Agostino Jul 08 '20 at 11:13
A TextField
is a component that always has a value of type String
. When binding a property of another type to a text field, the value is automatically converted if the conversion between the two types is supported.
public class MyBean {
private int value;
public int getValue() {
return value;
}
public void setValue(int integer) {
value = integer;
}
}
The property named "value" from a BeanItem
constructed from MyBean
will be of type Integer
. Binding the property to a TextField
will automatically make validation fail for texts that can not be converted to an Integer.
final MyBean myBean = new MyBean();
BeanItem<MyBean> beanItem = new BeanItem<MyBean>(myBean);
final Property<Integer> integerProperty = (Property<Integer>) beanItem
.getItemProperty("value");
final TextField textField = new TextField("Text field", integerProperty);
Button submitButton = new Button("Submit value", new ClickListener() {
public void buttonClick(ClickEvent event) {
String uiValue = textField.getValue();
Integer propertyValue = integerProperty.getValue();
int dataModelValue = myBean.getValue();
Notification.show("UI value (String): " + uiValue
+ "\nProperty value (Integer): " + propertyValue
+ "\nData model value (int): " + dataModelValue);
}
});
addComponent(new Label("Text field type: " + textField.getType()));
addComponent(new Label("Text field type: " + integerProperty.getType()));
addComponent(textField);
addComponent(submitButton);
With this example, entering a number and pressing the button causes the value of the TextField
to be a String
, the property value will be an Integer
representing the same value and the value in the bean will be the same int. If e.g. a letter is entered to the field and the button is pressed, the validation will fail. This causes a notice to be displayed for the field. The field value is still updated, but the property value and the bean value are kept at their previous values.
This is an update (2017 with vaadin 8) for @raffael answer:
public class DoubleField extends TextField implements ValueChangeListener<String> {
public String lastValue;
public DoubleField() {
setValueChangeMode(ValueChangeMode.EAGER);
addValueChangeListener(this);
lastValue="";
}
@Override
public void valueChange(ValueChangeEvent<String> event) {
String text = (String) event.getValue();
try {
new Double(text);
lastValue = text;
} catch (NumberFormatException e) {
setValue(lastValue);
}
}

- 5,179
- 10
- 35
- 56

- 76
- 5