In my application I have a screen with three fields which I need to validate, and a Save button.
I bind save button "disable property" to fields' "text property" matching some pattern (simplified patterns in this example, doesn't matter):
public void initialize(){
saveNetworkBtn.disableProperty()
.bind(textPropertyBindingPattern(ipInp, Pattern.compile("[0-9]{3}"))
.or(textPropertyBindingPattern(subnetInp, Pattern.compile("[0-9]{3}")))
.or(textPropertyBindingPattern(gatewayInp, Pattern.compile("[0-9]{3}"))));
}
private BooleanBinding textPropertyBindingPattern(TextField textField, Pattern pattern ) {
return Bindings.createBooleanBinding(() ->
!pattern.matcher(textField.getText()).matches(), textField.textProperty());
}
So that save button is locked until all values are correct:
But I need to highlight incorrect fields also with some red border like
-fx-border-color: red;
My main goal is to handle this in one place instead of adding several listeners. Is it possible to bing this somehow in the code above or I need to add listeners to each field?
Solved by adding a listener to binding, which adds a style to received text field:
private BooleanBinding textPropertyBindingPattern(TextField textField, Pattern pattern) {
BooleanBinding binding = Bindings.createBooleanBinding(() ->
!pattern.matcher(textField.getText()).matches(), textField.textProperty());
applyValidationClass(textField, binding.get());
binding.addListener((obs, oldValue, newValue) -> {
applyValidationClass(textField, newValue);
});
return binding ;
}
private void applyValidationClass(TextField textField, boolean isInvalid) {
textField.pseudoClassStateChanged(PseudoClass.getPseudoClass("incorrect-value"), isInvalid);
}
and 'incorrect-value' described in CSS file:
TextField:incorrect-value {
-fx-border-color: red;
}
Visualisation: https://www.screencast.com/t/4NKEjjopvaE7