### Validator Setup and Basic Checks Source: https://context7.com/effad/validatorfx/llms.txt Initialize a Validator, create checks for username and email fields, and bind a submit button's disabled state to validation errors. This example demonstrates immediate validation mode. ```java import net.synedra.validatorfx.Validator; import net.synedra.validatorfx.Severity; import javafx.beans.binding.Bindings; import javafx.scene.control.*; Validator validator = new Validator(); TextField usernameField = new TextField(); TextField emailField = new TextField(); // Check 1: username must be non-empty and lowercase validator.createCheck() .dependsOn("username", usernameField.textProperty()) .withMethod(c -> { String v = c.get("username"); if (v == null || v.isBlank()) { c.error("Username is required."); } else if (!v.equals(v.toLowerCase())) { c.error("Username must be lowercase."); } }) .decorates(usernameField) .immediate(); // Check 2: basic e-mail format warning (non-blocking) validator.createCheck() .dependsOn("email", emailField.textProperty()) .withMethod(c -> { String v = c.get("email"); if (!v.contains("@")) { c.warn("Value does not look like an e-mail address."); } }) .decorates(emailField) .immediate(); // Bind a submit button's disabled state to validation errors Button submitBtn = new Button("Submit"); submitBtn.disableProperty().bind(validator.containsErrorsProperty()); // Programmatic on-submit validation (explicit mode) submitBtn.setOnAction(e -> { if (validator.validate()) { System.out.println("Form is valid — proceeding."); } else { System.out.println("Errors: " + validator.createStringBinding().get()); // e.g. "• Username is required.\n• ..." } }); // Query state at any time boolean hasErrors = validator.containsErrors(); boolean hasWarnings = validator.containsWarnings(); validator.getValidationResult().getMessages() .forEach(m -> System.out.println(m.getSeverity() + ": " + m.getText())); ``` -------------------------------- ### Custom Decoration with `decoratingWith` Source: https://context7.com/effad/validatorfx/llms.txt Replace the default decoration factory with a custom one using `decoratingWith`. This example updates a label instead of showing an icon. ```java Validator validator = new Validator(); TextField s1 = new TextField("10"); TextField s2 = new TextField("5"); TextField result = new TextField("14"); Label statusLabel = new Label("OK"); validator.createCheck() .dependsOn("s1", s1.textProperty()) .dependsOn("s2", s2.textProperty()) .dependsOn("res", result.textProperty()) .withMethod(c -> { try { int a = Integer.parseInt(c.get("s1")); int b = Integer.parseInt(c.get("s2")); int r = Integer.parseInt(c.get("res")); if (a + b != r) { c.error("Sum should be " + (a + b)); } } catch (NumberFormatException e) { c.error("All values must be numbers."); } }) // Custom decoration: update a label instead of showing an icon .decoratingWith(msg -> new Decoration() { @Override public void add(Node target) { ((Label) target).setText("ERR – " + msg.getText()); } @Override public void remove(Node target) { ((Label) target).setText("OK"); } }) .decorates(statusLabel) .immediate(); ``` -------------------------------- ### Implement Validation Logic Source: https://github.com/effad/validatorfx/blob/master/README.md Defines the custom validation logic to be executed. Access dependencies using the provided context object. Multiple calls to withMethod install multiple checks. ```java .withMethod(c -> { String userName = c.get("username"); if (!userName.toLowerCase().equals(userName)) { c.error("Please use only lowercase letters."); } }) ``` -------------------------------- ### Minimal ValidatorFX Example Source: https://github.com/effad/validatorfx/blob/master/README.md A basic JavaFX application demonstrating ValidatorFX for form validation. It sets up a TextField and applies an immediate validation check for lowercase letters. ```java package net.synedra.validatorfx.demo; import javafx.application.Application; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.TextField; import javafx.scene.layout.GridPane; import javafx.stage.Stage; import net.synedra.validatorfx.Validator; public class MinimalExample extends Application { private Validator validator = new Validator(); @Override public void start(Stage primaryStage) throws Exception { TextField userTextField = new TextField(); validator.createCheck() .dependsOn("username", userTextField.textProperty()) .withMethod(c -> { String userName = c.get("username"); if (!userName.toLowerCase().equals(userName)) { c.error("Please use only lowercase letters."); } }) .decorates(userTextField) .immediate(); GridPane grid = createGrid(); grid.add(userTextField, 1, 1); Scene scene = new Scene(grid); primaryStage.setScene(scene); primaryStage.show(); } private GridPane createGrid() { GridPane grid = new GridPane(); grid.setAlignment(Pos.CENTER); grid.setPrefSize(400, 200); return grid; } public static void main(String[] args) { launch(); } } ``` -------------------------------- ### DefaultDecoration Strategies Source: https://context7.com/effad/validatorfx/llms.txt Provides built-in decoration factories for styling validation feedback. `createGraphicDecoration` adds an icon with a tooltip, while `createStyleClassDecoration` toggles CSS classes. ```java // Use CSS-class-based decorations globally (e.g. for custom themes) DefaultDecoration.setFactory(DefaultDecoration::createStyleClassDecoration); // Now all checks without an explicit decoratingWith() will toggle: // "validatorfx-error" or "validatorfx-warning" on the target node // Customize the default graphic decoration (e.g. increase tooltip font size) DefaultDecoration.setFactory(msg -> { GraphicDecoration decoration = DefaultDecoration.createGraphicDecoration(msg); Node node = decoration.getDecorationNode(); if (node instanceof Label lbl && lbl.getTooltip() != null) { lbl.getTooltip().setStyle(lbl.getTooltip().getStyle() + "-fx-font-size: 14px;"); } return decoration; }); // Reset to default graphic factory DefaultDecoration.setFactory(DefaultDecoration::createGraphicDecoration); ``` -------------------------------- ### Provide Custom Default Decoration Factory Source: https://github.com/effad/validatorfx/blob/master/README.md Set a custom factory for default decorations using `DefaultDecoration.setFactory(...)`. This allows modification of default graphic decorations. ```java DefaultDecoration.setFactory(this::createGraphicDecoration); ... public GraphicDecoration createGraphicDecoration(ValidationMessage message) { GraphicDecoration decoration = DefaultDecoration.createGraphicDecoration(message); if (decoration.getDecorationNode() instanceof Label label && label.getTooltip() instanceof Tooltip tooltip) { tooltip.setStyle(tooltip.getStyle() + "-fx-font-size: 20em"); } return decoration; } ``` -------------------------------- ### DefaultDecoration Source: https://context7.com/effad/validatorfx/llms.txt Provides built-in decoration strategies for visual feedback, including graphic overlays and CSS class toggling. ```APIDOC ## `DefaultDecoration` — Built-in Decoration Strategies `DefaultDecoration` provides two ready-made decoration factories and a global factory override. `createGraphicDecoration` overlays a small error/warning icon with a styled tooltip. `createStyleClassDecoration` toggles CSS classes (`validatorfx-error`, `validatorfx-warning`) for stylesheet-driven styling. Call `DefaultDecoration.setFactory(...)` to replace the global default for all checks. ```java // Use CSS-class-based decorations globally (e.g. for custom themes) DefaultDecoration.setFactory(DefaultDecoration::createStyleClassDecoration); // Now all checks without an explicit decoratingWith() will toggle: // "validatorfx-error" or "validatorfx-warning" on the target node // Customize the default graphic decoration (e.g. increase tooltip font size) DefaultDecoration.setFactory(msg -> { GraphicDecoration decoration = DefaultDecoration.createGraphicDecoration(msg); Node node = decoration.getDecorationNode(); if (node instanceof Label lbl && lbl.getTooltip() != null) { lbl.getTooltip().setStyle(lbl.getTooltip().getStyle() + "-fx-font-size: 14px;"); } return decoration; }); // Reset to default graphic factory DefaultDecoration.setFactory(DefaultDecoration::createGraphicDecoration); ``` ``` -------------------------------- ### Check.decorates() and Check.decoratingWith() Source: https://context7.com/effad/validatorfx/llms.txt Specifies which UI nodes receive visual feedback upon validation failure using `decorates(Node)`. `decoratingWith(Function)` allows for custom decoration factories, replacing the default behavior. ```APIDOC ## `Check.decorates()` and `Check.decoratingWith()` — Decoration Targets and Factories `decorates(Node)` specifies which node(s) receive decorations when the check fails. `decoratingWith(Function)` replaces the default graphic decoration factory for this specific check with a custom one. ```java Validator validator = new Validator(); TextField s1 = new TextField("10"); TextField s2 = new TextField("5"); TextField result = new TextField("14"); Label statusLabel = new Label("OK"); validator.createCheck() .dependsOn("s1", s1.textProperty()) .dependsOn("s2", s2.textProperty()) .dependsOn("res", result.textProperty()) .withMethod(c -> { try { int a = Integer.parseInt(c.get("s1")); int b = Integer.parseInt(c.get("s2")); int r = Integer.parseInt(c.get("res")); if (a + b != r) { c.error("Sum should be " + (a + b)); } } catch (NumberFormatException e) { c.error("All values must be numbers."); } }) // Custom decoration: update a label instead of showing an icon .decoratingWith(msg -> new Decoration() { @Override public void add(Node target) { ((Label) target).setText("ERR – " + msg.getText()); } @Override public void remove(Node target) { ((Label) target).setText("OK"); } }) .decorates(statusLabel) .immediate(); ``` ``` -------------------------------- ### Provide Custom Decorations Per Check Instance Source: https://github.com/effad/validatorfx/blob/master/README.md Use `decoratingWith` to apply custom decorations to individual validation checks. Requires a `Decoration` implementation. ```java validator.createCheck() ... .decoratingWith(this::sumDecorator) ... ; ... private Decoration sumDecorator(ValidationMessage m) { return new Decoration() { @Override public void remove(Node target) { ((Label) target).setText("OK"); } @Override public void add(Node target) { ((Label) target).setText("ERR - " + m.getText()); } }; } ``` -------------------------------- ### GraphicDecoration for Overlay Nodes Source: https://context7.com/effad/validatorfx/llms.txt Allows placing an arbitrary Node as a decoration on top of a target, with configurable position and offsets. `updateDecorations` can manually trigger layout refreshes. ```java // Custom icon overlay at bottom-right with a 4 px offset ImageView warningIcon = new ImageView(new Image("/icons/custom-warning.png")); GraphicDecoration customDeco = new GraphicDecoration(warningIcon, Pos.BOTTOM_RIGHT, -4, -4); // Use it on a specific check validator.createCheck() .dependsOn("val", someField.textProperty()) .withMethod(c -> { if (c.get("val").toString().isBlank()) c.warn("Required."); }) .decoratingWith(msg -> new GraphicDecoration( new ImageView(new Image("/icons/custom-" + msg.getSeverity().toString().toLowerCase() + ".png")), Pos.TOP_RIGHT )) .decorates(someField) .immediate(); // Force layout refresh after an animated transition moves decorated nodes GraphicDecoration.updateDecorations(someField); ``` -------------------------------- ### TooltipWrapper Source: https://context7.com/effad/validatorfx/llms.txt Wraps a Node to bind its disableProperty and show a Tooltip explaining the reason for being disabled, addressing JDK-8090379. ```APIDOC ## `TooltipWrapper` — Disabled Button with Explanatory Tooltip `TooltipWrapper` wraps any `Node` in an `HBox`, binds its `disableProperty` to a supplied `ObservableValue`, and shows a `Tooltip` explaining why the node is disabled — working around JDK-8090379 (tooltips do not fire on disabled JavaFX controls). ```java Validator validator = new Validator(); Button signUpBtn = new Button("Sign Up"); // Disable the button when there are errors; show what's wrong on hover TooltipWrapper