bashoogzaad
bashoogzaad

Reputation: 4781

Keep showing a dialog when validation of input fails

I currently have a dialog with four TextFields from which the input is collected. When the input can not meet my requirements, the dialog should stay open and show an error message. I currently have the following code:

dlg.setResultConverter(dialogButton -> {

    if (dialogButton == createButtonType) {

        ArrayList<String> returnList = getInput();

        if (returnList != null) {
            return returnList;
        }
        else {
            dlg.showAndWait();
        }

    }
    return null;
});

Optional<ArrayList<String>> result = dlg.showAndWait();
result.ifPresent(customerDetails -> {

    //Use the input for something

});

The getInput() method gets the text from the TextFields and tests it against some requirements. When the input passes, the four Strings are put in an ArrayList<String>. Else, the method returns null. As you can see, the result converter checks if the method returned null. If it didn't, it just returns the ArrayList<String>.

But, when the validation fails, the dialog should be kept open. It works with dlg.showAndWait(), but the downside is that it triggers an error: java.lang.IllegalStateException: Stage already visible. (it keeps working, but getting an error is not the way it should be)

My question is: does anyone know how to do this, without triggering an error?

Note: I am using JavaFX 8 (JDK 1.8.0_40), which has the dialog features built in.

Upvotes: 10

Views: 7922

Answers (3)

prasad_
prasad_

Reputation: 14287

Assume a Dialog with TextField and an Ok Button.

The button is disabled to start with and is enabled on entering valid data in the TextField (text between 5 and 25 characters long). The ChangeListener attached to the TextField's StringProperty controls the button's enabled/disabled state.

TextField textFld = new TextField();
...
ButtonType buttonTypeOk = new ButtonType("Okay", ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().add(buttonTypeOk);
final Button okButton = (Button) dialog.getDialogPane().lookupButton(buttonTypeOk);
okButton.setDisable(true);
textFld.textProperty().addListener((observable, oldValue, newValue) -> {
    okButton.setDisable(newValue.trim().length() < 5 || newValue.trim().length() > 25);
});

Upvotes: 0

Dave_cz
Dave_cz

Reputation: 1210

final Button okButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
okButton.addEventFilter(ActionEvent.ACTION, ae -> {
    if (!isValid()) {
        ae.consume(); //not valid
    }
});

Works fine for me. Just use filter as it fires first.

BTW it is described in official docs.

Upvotes: 24

eckig
eckig

Reputation: 11134

Add listeners to your TextFields, validating the user input.

If the user input is valid, enable the "OK" Button (or whatever its name is) if the user input is invalid, disable the Button.

If the Button for closing the Dialog is disabled, the only way to close the Dialog is to cancel, which results in an empty Optional as result.

Upvotes: 7

Related Questions