effad / ValidatorFX

A form validation library for JavaFX
BSD 3-Clause "New" or "Revised" License
221 stars 19 forks source link

Allow iteration over all dependencies in a check #27

Closed effad closed 1 year ago

effad commented 2 years ago

Consider the case where a check is programmatically built out of a set of objects, e.g.

Check check = validator.createCheck()
    .withMethod(this::atLeastOneParameter);
for (ComboFormField<?> combo : combos.values()) {
    check
        .dependsOn(combo.getDataIndex(), combo.chosenItemProperty())
        .decorates(combo.getPresentation())
    ;
}
check.immediate()

Now in the check-Method we must iterate over all the given properties to check if at least one value was given, but there is no way to do that easily:

private void atLeastOneParameter(Check.Context check) {
    // TODO :: iterate over all dependencies
}

We must iterate over combos again and pick the same property, which violates the DRY principle and inserts an ugly dependency between the two places in the code.

effad commented 1 year ago

Fixed this issue but forgot to close it. ValidatorFXDemo now contains:

        Check cbCheck = validator.createCheck()
                .withMethod(this::oneMustBeChecked);
        HBox cbBox = new HBox(15);
        for (int i = 0; i < 5; i++) {
            CheckBox cb = new CheckBox("Option #" + i);
            cbBox.getChildren().add(cb);
            cbCheck
                .dependsOn("cb" + i, cb.selectedProperty())
                .decorates(cb)
            ;
        }
        cbCheck.immediate();

together with:

    private void oneMustBeChecked(Check.Context c) {
        boolean oneIsChecked = false;
        for (String key : c.keys()) {
            oneIsChecked = oneIsChecked || c.get(key).equals(Boolean.TRUE);
        }
        if (!oneIsChecked) {
            c.error("At least one option must be checked.");
        }
    }