Search code examples
javaformsvalidationjavafxcontrolsfx

Validate JavaFX form only after submission using ValidationSupport


I'm trying to validate a javafx form using ValidationSupport, the validation is working, but when I access the form the "errors decorations" are already shown, even before the form is submitted or the textfield is focused.

ValidationSupport validationSupport = new ValidationSupport();
    validationSupport.registerValidator(textField, Validator.createEmptyValidator("Text is required"));

The following image shows an example of the form in its initial state.

My Form

How can I force the decoration to show only after the user submit the form or change the TextField value?


Solution

  • To validate controls on demand is an issue (on-demand validation option) on ControlsFx's issue tracker which is still open so ControlsFx does NOT support it yet.

    But there is a way to suppress error decorations:

    ValidationSupport validationSupport = new ValidationSupport();
    validationSupport.setErrorDecorationEnabled(false);
    

    Later, when you actually want to validate (on submit button for example) you need to reset it to default value:

    validationSupport.setErrorDecorationEnabled(true);
    validationSupport.redecorate();
    

    This way, fields still get validated by every change but error decorations are not shown until you actually want them to be shown.


    Example:

    In this example we'd like to see validation errors only if number field has the focus.

    public class Sandbox extends Application {
        @Override
        public void start(Stage primaryStage) throws Exception {
            GridPane pane = new GridPane();
            pane.add(new Label("Number field:"), 0 , 0);
            TextField numberField = new TextField("");
            pane.add(numberField, 1, 0);
            TextField textField = new TextField("");
            pane.add(new Label("Text field:"), 0, 1);
            pane.add(textField, 1, 1);
    
            ValidationSupport vs = new ValidationSupport();
            vs.setErrorDecorationEnabled(false); // we don't want errors to bother us for now.
            vs.registerValidator(numberField, Validator.createRegexValidator("must be digits only!", "\\d*", Severity.ERROR));
    
            // validate and show errors only if number field has the focus
            vs.errorDecorationEnabledProperty().bind(numberField.focusedProperty());
    
            primaryStage.setScene(new Scene(pane));
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            Application.launch(Sandbox.class);
        }
    }
    

    or if you want to see validation errors only after submit button is clicked for the first time:

            ...
            Button button = new Button("Submit");
            pane.add(button, 0, 2);
    
            ValidationSupport vs = new ValidationSupport();
            vs.setErrorDecorationEnabled(false); // we don't want errors to bother us for now.
            vs.registerValidator(numberField, Validator.createRegexValidator("must be digits only!", "\\d*", Severity.ERROR));
    
            
            button.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    vs.setErrorDecorationEnabled(true); // validate and show errors now!
                }
            });
            ...