4

I need to validate simple JavaFX form with password and password confirmation.

validationSupport.registerValidator(passwordInput,
                  Validator.createEmptyValidator("Password required!"));
validationSupport.registerValidator(confirmPasswordInput,
                  new EqualsToValidator(passwordInput.textProperty(),
                                  "Password differs from confirmation"));

In EqualsToValidator I simply compare property.getValue() and value passed to validator.

If I change only password EqualsToValidator is not called because it is listening to confirmPasswordInput not passwordInput.

I have only found ugly solution:

passwordInput.textProperty().addListener((observable, oldValue, newValue) -> {
    String oldText = confirmPasswordInput.getText();
    confirmPasswordInput.setText(null);
    confirmPasswordInput.setText(oldText);
});

How to invalidate one field when another field changes?

Denis Kokorin
  • 887
  • 8
  • 17

2 Answers2

1

My implementation

Validator.java - base class for validator.

TextValidator.java and PasswordValidator.java - implementations.

ValidationSupport.java tracks all validators.

Usage:

validationSupport.addValidator(new TextValidator(usernameInput, "Username is required!"));
validationSupport.addValidator(new TextValidator(passwordInput, "Password is required!"));
validationSupport.addValidator(new PasswordValidator(passwordInput, confirmPasswordInput, "Password differs from confirmation"));
Denis Kokorin
  • 887
  • 8
  • 17
-1

This worked for me. I simply copied the ValidationSupport class and added the folowing code.

@SuppressWarnings("unchecked")
public <T> void reaplyValidator(Control target){

    if(!controls.containsKey(target)){
        throw new NullPointerException("The given control was not registered");
    }

    ValueExtractor.getObservableValueExtractor(target).map( e -> {

        ObservableValue<T> observable = (ObservableValue<T>) e.call(target);
        Validator<T> validator = (Validator<T>) controls.get(target);

        Platform.runLater(() -> validationResults.put(target, validator.apply(target, observable.getValue())));

        dataChanged.set(true);

        return e;

    });
}

public void revalidate(){
    for(Control c : getRegisteredControls()){
        reaplyValidator(c);
    }
}

You also need to change the controls Set to a Map in order to keep the validator.

private ObservableMap<Control, Validator<?>> controls = FXCollections.observableMap(new HashMap<>());
dinhokz
  • 895
  • 15
  • 36