Griffon - restricting a textfield to numbers

With my latest Griffon+JavaFX application, I wasn't having any luck binding a textfield to a 'float' property in my model. So to work around it temporarily, I've added a change listener which will veto any input that isn't a number.

This example is basically using a very Java centric approach:
import javafx.beans.value.ChangeListener
import javafx.beans.value.ObservableValue
import org.apache.commons.lang.StringUtils
// model
@FXBindable String amount1
// view
textField(id: 'amount1', text: bind(model.amount1Property))
noparent {
amount1.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable,
String oldValue, String newValue) {
try {
if (StringUtils.isNotBlank(newValue)) {
Integer.parseInt(newValue);
}
} catch (Exception e) {
observable.setValue(oldValue);
}
}
});
}
Now, we can simplify this by using the Groovy way:
import javafx.beans.value.ChangeListener
import javafx.beans.value.ObservableValue
import org.apache.commons.lang.StringUtils
// model
@FXBindable String amount1
// view
textField(id: 'amount1', text: bind(model.amount1Property))
noparent {
amount1.textProperty().addListener({ ObservableValue<? extends String> observable, String oldValue, String newValue ->
try {
if (StringUtils.isNotBlank(newValue)) {
Integer.parseInt(newValue);
}
} catch (Exception e) {
observable.setValue(oldValue);
}
} as ChangeListener<String>)
}
See Groovy way to implement interfaces to understand how this is implementing the interface.

If we want to have several text fields using the same logic, we can define the closure in the Controller and reference that in many places:
import javafx.beans.value.ChangeListener
import javafx.beans.value.ObservableValue
import org.apache.commons.lang.StringUtils
// model
@FXBindable String amount1
@FXBindable String amount2
// view
textField(id: 'amount1', text: bind(model.amount1Property))
textField(id: 'amount2', text: bind(model.amount2Property))
noparent {
amount1.textProperty().addListener(controller.restrictToNumber)
amount2.textProperty().addListener(controller.restrictToNumber)
}
// controller
def restrictToNumber = { ObservableValue<? extends String> observable, String oldValue, String newValue ->
try {
if (StringUtils.isNotBlank(newValue)) {
Integer.parseInt(newValue);
}
} catch (Exception e) {
observable.setValue(oldValue);
}
} as ChangeListener<String>
Still, this is not optimal since I have to use Strings instead of Floats in my model - but it does let me continue with whats important right now. Hopefully the binding bug can be fixed soon.

Popular posts from this blog

AspectJWeaver with JDK 7 - error - only supported at Java 5 compliance level or above

JUnit parameterized test with Spring autowiring AND transactions

Intellij tip - Joining multiple lines into one